diff options
author | YamaArashi <shadow962@live.com> | 2016-02-11 01:12:34 -0800 |
---|---|---|
committer | YamaArashi <shadow962@live.com> | 2016-02-11 01:12:34 -0800 |
commit | b84b6b23fa58beb5674b37279742eb65461ca076 (patch) | |
tree | a85da124cbf9f888a31b750ede3a832c2c6b96aa /gcc/config/pa | |
parent | 23e2a17097740709d4466a802e03992116b12900 (diff) |
delete irrelevant configs
Diffstat (limited to 'gcc/config/pa')
-rwxr-xr-x | gcc/config/pa/ee.asm | 261 | ||||
-rwxr-xr-x | gcc/config/pa/ee_fp.asm | 274 | ||||
-rwxr-xr-x | gcc/config/pa/lib1funcs.asm | 1146 | ||||
-rwxr-xr-x | gcc/config/pa/lib2funcs.asm | 74 | ||||
-rwxr-xr-x | gcc/config/pa/pa-gas.h | 22 | ||||
-rwxr-xr-x | gcc/config/pa/pa-hiux.h | 26 | ||||
-rwxr-xr-x | gcc/config/pa/pa-hpux.h | 49 | ||||
-rwxr-xr-x | gcc/config/pa/pa-hpux10.h | 89 | ||||
-rwxr-xr-x | gcc/config/pa/pa-hpux11.h | 98 | ||||
-rwxr-xr-x | gcc/config/pa/pa-hpux7.h | 37 | ||||
-rwxr-xr-x | gcc/config/pa/pa-hpux9.h | 31 | ||||
-rwxr-xr-x | gcc/config/pa/pa-oldas.h | 22 | ||||
-rwxr-xr-x | gcc/config/pa/pa-osf.h | 42 | ||||
-rwxr-xr-x | gcc/config/pa/pa-pro-end.h | 42 | ||||
-rwxr-xr-x | gcc/config/pa/pa-pro.h | 79 | ||||
-rwxr-xr-x | gcc/config/pa/pa.c | 6491 | ||||
-rwxr-xr-x | gcc/config/pa/pa.h | 2601 | ||||
-rwxr-xr-x | gcc/config/pa/pa.md | 5729 | ||||
-rwxr-xr-x | gcc/config/pa/pa1.h | 28 | ||||
-rwxr-xr-x | gcc/config/pa/rtems.h | 31 | ||||
-rwxr-xr-x | gcc/config/pa/t-dce-thr | 5 | ||||
-rwxr-xr-x | gcc/config/pa/t-pa | 18 | ||||
-rwxr-xr-x | gcc/config/pa/t-pro | 38 | ||||
-rwxr-xr-x | gcc/config/pa/x-pa | 3 | ||||
-rwxr-xr-x | gcc/config/pa/x-pa-hpux | 4 | ||||
-rwxr-xr-x | gcc/config/pa/xm-pa.h | 62 | ||||
-rwxr-xr-x | gcc/config/pa/xm-pahpux.h | 61 | ||||
-rwxr-xr-x | gcc/config/pa/xm-papro.h | 58 |
28 files changed, 0 insertions, 17421 deletions
diff --git a/gcc/config/pa/ee.asm b/gcc/config/pa/ee.asm deleted file mode 100755 index 787bda7..0000000 --- a/gcc/config/pa/ee.asm +++ /dev/null @@ -1,261 +0,0 @@ -; Subroutines for out of line prologues and epilogues on for the HPPA -; Copyright (C) 1994, 1995, 1996 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. - -; 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. - - .SPACE $PRIVATE$ - .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31 - .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82 - .SPACE $TEXT$ - .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44 - .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY - .SUBSPA $MILLICODE$,QUAD=0,ALIGN=8,ACCESS=44,SORT=8 - -; This is an out-of-line prologue. -; -; It performs the following operations: -; -; * Saves the return pointer at sp - 20 -; -; * Creates a new stack frame (sp'), size of the frame is passed in %r21 -; -; * The old stack pointer is saved at sp (frame pointer version only). -; -; * Saves grs (passed in low 16 bits of %r22 into the stack frame -; at sp' + local_fsize (passed in %r19). -; -; * Saves frs (passed in high 16 bits of %r22) into the stack -; frame at sp' + local_fsize (passed in %r19). -; -; * Sets up a frame pointer (in %r3) (frame pointer version only). -; -; * Returns to the instruction _immediately_ after the call to -; this function. - - .SPACE $TEXT$ - .SUBSPA $MILLICODE$ - .EXPORT __outline_prologue,MILLICODE - .align 32 -__outline_prologue - .PROC - .CALLINFO FRAME=0,NO_CALLS - .ENTRY - copy %r30,%r20 - - ; Subtract 4 from our return pointer so that we return to - ; the right location. - ldo -4(%r31),%r31 - - ; Save off %r2 - stw %r2,-20(0,%r30) - - ; Make our new frame. - add %r21,%r30,%r30 - - ; Add in local_fsize to our frame pointer so we do register - ; saves into the right place - add %r20,%r19,%r20 - - ; %r22 tells us what registers we need to save. The upper half - ; is for fp registers, the lower half for integer registers. - ; We put the lower half in %r1 and the upper half into %r22 - ; for later use. - extru %r22,31,16,%r1 - extrs %r22,15,16,%r22 - - ; %r1 now olds a value 0-18 which corresponds to the number - ; of grs we need to save. We need to reverse that value so - ; we can just into the table and straight-line execute to the - ; end of the gr saves. - comb,= %r0,%r1,L$0000 - subi 18,%r1,%r1 - blr,n %r1,%r0 - b,n L$0000 - stws,ma %r18,4(0,%r20) - nop - stws,ma %r17,4(0,%r20) - nop - stws,ma %r16,4(0,%r20) - nop - stws,ma %r15,4(0,%r20) - nop - stws,ma %r14,4(0,%r20) - nop - stws,ma %r13,4(0,%r20) - nop - stws,ma %r12,4(0,%r20) - nop - stws,ma %r11,4(0,%r20) - nop - stws,ma %r10,4(0,%r20) - nop - stws,ma %r9,4(0,%r20) - nop - stws,ma %r8,4(0,%r20) - nop - stws,ma %r7,4(0,%r20) - nop - stws,ma %r6,4(0,%r20) - nop - stws,ma %r5,4(0,%r20) - nop - stws,ma %r4,4(0,%r20) - nop - stws,ma %r3,4(0,%r20) - nop -L$0000 - ; All gr saves are done. Align the temporary frame pointer and - ; do the fr saves. - ldo 7(%r20),%r20 - depi 0,31,3,%r20 - - comb,= %r0,%r22,L$0001 - subi 21,%r22,%r22 - blr,n %r22,%r0 - b,n L$0001 - fstws,ma %fr21,8(0,%r20) - nop - fstws,ma %fr20,8(0,%r20) - nop - fstws,ma %fr19,8(0,%r20) - nop - fstws,ma %fr18,8(0,%r20) - nop - fstws,ma %fr17,8(0,%r20) - nop - fstws,ma %fr16,8(0,%r20) - nop - fstws,ma %fr15,8(0,%r20) - nop - fstws,ma %fr14,8(0,%r20) - nop - fstws,ma %fr13,8(0,%r20) - nop - fstws,ma %fr12,8(0,%r20) - nop -L$0001 - ; Return - bv,n 0(%r31) - .EXIT - .PROCEND - - - - .EXPORT __outline_epilogue,MILLICODE - .align 32 -__outline_epilogue - .PROC - .CALLINFO FRAME=0,NO_CALLS - .ENTRY - ; Get our original stack pointer and put it in %r20 - sub %r30,%r21,%r20 - - ; Subtract 4 from our return pointer so that we return to - ; the right location. - ldo -4(%r31),%r31 - - ; Reload %r2 - ldw -20(0,%r20),%r2 - - ; Add in local_fsize (%r19) to the frame pointer to find - ; the saved registers. - add %r20,%r19,%r20 - - ; %r22 tells us what registers we need to restore. The upper half - ; is for fp registers, the lower half for integer registers. - ; We put the lower half in %r1 and the upper half into %r22 - ; for later use. - extru %r22,31,16,%r1 - extrs %r22,15,16,%r22 - - ; %r1 now olds a value 0-18 which corresponds to the number - ; of grs we need to restore. We need to reverse that value so - ; we can just into the table and straight-line execute to the - ; end of the gr restore. - comb,= %r0,%r1,L$0004 - subi 18,%r1,%r1 - blr,n %r1,%r0 - b,n L$0004 - ldws,ma 4(0,%r20),%r18 - nop - ldws,ma 4(0,%r20),%r17 - nop - ldws,ma 4(0,%r20),%r16 - nop - ldws,ma 4(0,%r20),%r15 - nop - ldws,ma 4(0,%r20),%r14 - nop - ldws,ma 4(0,%r20),%r13 - nop - ldws,ma 4(0,%r20),%r12 - nop - ldws,ma 4(0,%r20),%r11 - nop - ldws,ma 4(0,%r20),%r10 - nop - ldws,ma 4(0,%r20),%r9 - nop - ldws,ma 4(0,%r20),%r8 - nop - ldws,ma 4(0,%r20),%r7 - nop - ldws,ma 4(0,%r20),%r6 - nop - ldws,ma 4(0,%r20),%r5 - nop - ldws,ma 4(0,%r20),%r4 - nop - ldws,ma 4(0,%r20),%r3 - nop -L$0004 - ; All gr restore are done. Align the temporary frame pointer and - ; do the fr restore. - ldo 7(%r20),%r20 - depi 0,31,3,%r20 - - comb,= %r0,%r22,L$0005 - subi 21,%r22,%r22 - blr,n %r22,%r0 - b,n L$0005 - fldws,ma 8(0,%r20),%fr21 - nop - fldws,ma 8(0,%r20),%fr20 - nop - fldws,ma 8(0,%r20),%fr19 - nop - fldws,ma 8(0,%r20),%fr18 - nop - fldws,ma 8(0,%r20),%fr17 - nop - fldws,ma 8(0,%r20),%fr16 - nop - fldws,ma 8(0,%r20),%fr15 - nop - fldws,ma 8(0,%r20),%fr14 - nop - fldws,ma 8(0,%r20),%fr13 - nop - fldws,ma 8(0,%r20),%fr12 - nop -L$0005 - ; Return and deallocate our frame. - bv 0(%r31) - sub %r30,%r21,%r30 - .EXIT - .PROCEND diff --git a/gcc/config/pa/ee_fp.asm b/gcc/config/pa/ee_fp.asm deleted file mode 100755 index ef040cf..0000000 --- a/gcc/config/pa/ee_fp.asm +++ /dev/null @@ -1,274 +0,0 @@ -; Subroutines for out of line prologues and epilogues on for the HPPA -; Copyright (C) 1994, 1995, 1996 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. - -; 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. - - .SPACE $PRIVATE$ - .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31 - .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82 - .SPACE $TEXT$ - .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44 - .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY - .SUBSPA $MILLICODE$,QUAD=0,ALIGN=8,ACCESS=44,SORT=8 - - -; This is an out-of-line prologue. -; -; It performs the following operations: -; -; * Saves the return pointer at sp - 20 -; -; * Creates a new stack frame (sp'), size of the frame is passed in %r21 -; -; * The old stack pointer is saved at sp (frame pointer version only). -; -; * Saves grs (passed in low 16 bits of %r22 into the stack frame -; at sp' + local_fsize (passed in %r19). -; -; * Saves frs (passed in high 16 bits of %r22) into the stack -; frame at sp' + local_fsize (passed in %r19). -; -; * Sets up a frame pointer (in %r3) (frame pointer version only). -; -; * Returns to the instruction _immediately_ after the call to -; this function. - - .SPACE $TEXT$ - .SUBSPA $MILLICODE$ - .EXPORT __outline_prologue_fp,MILLICODE - .align 32 -__outline_prologue_fp - .PROC - .CALLINFO FRAME=0,NO_CALLS - .ENTRY - copy %r30,%r20 - - ; Subtract 4 from our return pointer so that we return to - ; the right location. - ldo -4(%r31),%r31 - - ; Save off %r2 - stw %r2,-20(0,%r30) - - ; Make our new frame. - add %r21,%r30,%r30 - - ; Save our old stack pointer. - stw %r20,0(0,%r20) - - ; Add in local_fsize to our frame pointer so we do register - ; saves into the right place - add %r20,%r19,%r20 - - ; %r22 tells us what registers we need to save. The upper half - ; is for fp registers, the lower half for integer registers. - ; We put the lower half in %r1 and the upper half into %r22 - ; for later use. - extru %r22,31,16,%r1 - extrs %r22,15,16,%r22 - - ; %r1 now olds a value 0-18 which corresponds to the number - ; of grs we need to save. We need to reverse that value so - ; we can just into the table and straight-line execute to the - ; end of the gr saves. - comb,= %r0,%r1,L$0002 - subi 18,%r1,%r1 - blr,n %r1,%r0 - b,n L$0002 - stws,ma %r18,4(0,%r20) - nop - stws,ma %r17,4(0,%r20) - nop - stws,ma %r16,4(0,%r20) - nop - stws,ma %r15,4(0,%r20) - nop - stws,ma %r14,4(0,%r20) - nop - stws,ma %r13,4(0,%r20) - nop - stws,ma %r12,4(0,%r20) - nop - stws,ma %r11,4(0,%r20) - nop - stws,ma %r10,4(0,%r20) - nop - stws,ma %r9,4(0,%r20) - nop - stws,ma %r8,4(0,%r20) - nop - stws,ma %r7,4(0,%r20) - nop - stws,ma %r6,4(0,%r20) - nop - stws,ma %r5,4(0,%r20) - nop - stws,ma %r4,4(0,%r20) - nop - stws,ma %r3,4(0,%r20) - nop -L$0002 - ; All gr saves are done. Align the temporary frame pointer and - ; do the fr saves. - ldo 7(%r20),%r20 - depi 0,31,3,%r20 - - comb,= %r0,%r22,L$0003 - subi 21,%r22,%r22 - blr,n %r22,%r0 - b,n L$0003 - fstws,ma %fr21,8(0,%r20) - nop - fstws,ma %fr20,8(0,%r20) - nop - fstws,ma %fr19,8(0,%r20) - nop - fstws,ma %fr18,8(0,%r20) - nop - fstws,ma %fr17,8(0,%r20) - nop - fstws,ma %fr16,8(0,%r20) - nop - fstws,ma %fr15,8(0,%r20) - nop - fstws,ma %fr14,8(0,%r20) - nop - fstws,ma %fr13,8(0,%r20) - nop - fstws,ma %fr12,8(0,%r20) - nop -L$0003 - ; Return, setting up a frame pointer in the delay slot - bv 0(%r31) - sub %r30,%r21,%r3 - .EXIT - .PROCEND - - -; This is an out-of-line epilogue. It's operation is basically the reverse -; of the out-of-line prologue. - - .EXPORT __outline_epilogue_fp,MILLICODE - .align 32 -__outline_epilogue_fp - .PROC - .CALLINFO FRAME=0,NO_CALLS - .ENTRY - ; Make a copy of our frame pointer into %r20 - copy %r3,%r20 - - ; Subtract 4 from our return pointer so that we return to - ; the right location. - ldo -4(%r31),%r31 - - ; Reload %r2 - ; First save off %r2 - ldw -20(0,%r20),%r2 - - ; Load our old stack pointer, save it in %r21. - ldw 0(0,%r20),%r21 - - ; Add in local_fsize (%r19) to the frame pointer to find - ; the saved registers. - add %r20,%r19,%r20 - - ; %r22 tells us what registers we need to restore. The upper half - ; is for fp registers, the lower half for integer registers. - ; We put the lower half in %r1 and the upper half into %r22 - ; for later use. - extru %r22,31,16,%r1 - extrs %r22,15,16,%r22 - - ; %r1 now olds a value 0-18 which corresponds to the number - ; of grs we need to restore. We need to reverse that value so - ; we can just into the table and straight-line execute to the - ; end of the gr restore. - comb,= %r0,%r1,L$0006 - subi 18,%r1,%r1 - blr,n %r1,%r0 - b,n L$0006 - ldws,ma 4(0,%r20),%r18 - nop - ldws,ma 4(0,%r20),%r17 - nop - ldws,ma 4(0,%r20),%r16 - nop - ldws,ma 4(0,%r20),%r15 - nop - ldws,ma 4(0,%r20),%r14 - nop - ldws,ma 4(0,%r20),%r13 - nop - ldws,ma 4(0,%r20),%r12 - nop - ldws,ma 4(0,%r20),%r11 - nop - ldws,ma 4(0,%r20),%r10 - nop - ldws,ma 4(0,%r20),%r9 - nop - ldws,ma 4(0,%r20),%r8 - nop - ldws,ma 4(0,%r20),%r7 - nop - ldws,ma 4(0,%r20),%r6 - nop - ldws,ma 4(0,%r20),%r5 - nop - ldws,ma 4(0,%r20),%r4 - nop - ldws,ma 4(0,%r20),%r3 - nop -L$0006 - ; All gr restore are done. Align the temporary frame pointer and - ; do the fr restore. - ldo 7(%r20),%r20 - depi 0,31,3,%r20 - - comb,= %r0,%r22,L$0007 - subi 21,%r22,%r22 - blr,n %r22,%r0 - b,n L$0007 - fldws,ma 8(0,%r20),%fr21 - nop - fldws,ma 8(0,%r20),%fr20 - nop - fldws,ma 8(0,%r20),%fr19 - nop - fldws,ma 8(0,%r20),%fr18 - nop - fldws,ma 8(0,%r20),%fr17 - nop - fldws,ma 8(0,%r20),%fr16 - nop - fldws,ma 8(0,%r20),%fr15 - nop - fldws,ma 8(0,%r20),%fr14 - nop - fldws,ma 8(0,%r20),%fr13 - nop - fldws,ma 8(0,%r20),%fr12 - nop -L$0007 - ; Return and deallocate our frame. - bv 0(%r31) - copy %r21,%r30 - .EXIT - .PROCEND - - diff --git a/gcc/config/pa/lib1funcs.asm b/gcc/config/pa/lib1funcs.asm deleted file mode 100755 index 95eb75e..0000000 --- a/gcc/config/pa/lib1funcs.asm +++ /dev/null @@ -1,1146 +0,0 @@ -; Low level integer divide, multiply, remainder, etc routines for the HPPA. -; Copyright (C) 1995 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.) - -; 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. - -#ifdef L_dyncall - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .export $$dyncall -$$dyncall - .proc - .callinfo frame=0,no_calls - .entry - bb,>=,n %r22,30,L$1 ; branch if not plabel address - depi 0,31,2,%r22 ; clear the two least significant bits - ldw 4(%sr0,%r22),%r19 ; load new LTP value - ldw 0(%sr0,%r22),%r22 ; load address of target -L$1 ldsid (%sr0,%r22),%r1 ; get the "space ident" selected by r22 - mtsp %r1,%sr0 ; move that space identifier into sr0 - be 0(%sr0,%r22) ; branch to the real target - stw %r2,-24(%sr0,%r30) ; save return address into frame marker - .exit - .procend -#endif - - -#ifdef L_multiply -#define op0 %r26 -#define op1 %r25 -#define res %r29 -#define ret %r31 -#define tmp %r1 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$mulU - .export $$mulI -$$mulU -$$mulI - .proc - .callinfo frame=0,no_calls - .entry - addi,tr 0,%r0,res ; clear out res, skip next insn -L$loop zdep op1,26,27,op1 ; shift up op1 by 5 -L$lo zdep op0,30,5,tmp ; extract next 5 bits and shift up - blr tmp,%r0 - extru op0,26,27,op0 ; shift down op0 by 5 -L$0 comib,<> 0,op0,L$lo - zdep op1,26,27,op1 ; shift up op1 by 5 - bv %r0(ret) - nop -L$1 b L$loop - addl op1,res,res - nop - nop -L$2 b L$loop - sh1addl op1,res,res - nop - nop -L$3 sh1addl op1,op1,tmp ; 3x - b L$loop - addl tmp,res,res - nop -L$4 b L$loop - sh2addl op1,res,res - nop - nop -L$5 sh2addl op1,op1,tmp ; 5x - b L$loop - addl tmp,res,res - nop -L$6 sh1addl op1,op1,tmp ; 3x - b L$loop - sh1addl tmp,res,res - nop -L$7 zdep op1,28,29,tmp ; 8x - sub tmp,op1,tmp ; 7x - b L$loop - addl tmp,res,res -L$8 b L$loop - sh3addl op1,res,res - nop - nop -L$9 sh3addl op1,op1,tmp ; 9x - b L$loop - addl tmp,res,res - nop -L$10 sh2addl op1,op1,tmp ; 5x - b L$loop - sh1addl tmp,res,res - nop -L$11 sh2addl op1,op1,tmp ; 5x - sh1addl tmp,op1,tmp ; 11x - b L$loop - addl tmp,res,res -L$12 sh1addl op1,op1,tmp ; 3x - b L$loop - sh2addl tmp,res,res - nop -L$13 sh1addl op1,op1,tmp ; 3x - sh2addl tmp,op1,tmp ; 13x - b L$loop - addl tmp,res,res -L$14 zdep op1,28,29,tmp ; 8x - sub tmp,op1,tmp ; 7x - b L$loop - sh1addl tmp,res,res -L$15 zdep op1,27,28,tmp ; 16x - sub tmp,op1,tmp ; 15x - b L$loop - addl tmp,res,res -L$16 zdep op1,27,28,tmp ; 16x - b L$loop - addl tmp,res,res - nop -L$17 zdep op1,27,28,tmp ; 16x - addl tmp,op1,tmp ; 17x - b L$loop - addl tmp,res,res -L$18 sh3addl op1,op1,tmp ; 9x - b L$loop - sh1addl tmp,res,res - nop -L$19 sh3addl op1,op1,tmp ; 9x - sh1addl tmp,op1,tmp ; 19x - b L$loop - addl tmp,res,res -L$20 sh2addl op1,op1,tmp ; 5x - b L$loop - sh2addl tmp,res,res - nop -L$21 sh2addl op1,op1,tmp ; 5x - sh2addl tmp,op1,tmp ; 21x - b L$loop - addl tmp,res,res -L$22 sh2addl op1,op1,tmp ; 5x - sh1addl tmp,op1,tmp ; 11x - b L$loop - sh1addl tmp,res,res -L$23 sh1addl op1,op1,tmp ; 3x - sh3addl tmp,res,res ; += 8x3 - b L$loop - sub res,op1,res ; -= x -L$24 sh1addl op1,op1,tmp ; 3x - b L$loop - sh3addl tmp,res,res ; += 8x3 - nop -L$25 sh2addl op1,op1,tmp ; 5x - sh2addl tmp,tmp,tmp ; 25x - b L$loop - addl tmp,res,res -L$26 sh1addl op1,op1,tmp ; 3x - sh2addl tmp,op1,tmp ; 13x - b L$loop - sh1addl tmp,res,res ; += 2x13 -L$27 sh1addl op1,op1,tmp ; 3x - sh3addl tmp,tmp,tmp ; 27x - b L$loop - addl tmp,res,res -L$28 zdep op1,28,29,tmp ; 8x - sub tmp,op1,tmp ; 7x - b L$loop - sh2addl tmp,res,res ; += 4x7 -L$29 sh1addl op1,op1,tmp ; 3x - sub res,tmp,res ; -= 3x - b L$foo - zdep op1,26,27,tmp ; 32x -L$30 zdep op1,27,28,tmp ; 16x - sub tmp,op1,tmp ; 15x - b L$loop - sh1addl tmp,res,res ; += 2x15 -L$31 zdep op1,26,27,tmp ; 32x - sub tmp,op1,tmp ; 31x -L$foo b L$loop - addl tmp,res,res - .exit - .procend -#endif - - -#ifdef L_divU -#define dividend %r26 -#define divisor %r25 -#define tmp %r1 -#define quotient %r29 -#define ret %r31 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU -$$divU - .proc - .callinfo frame=0,no_calls - .entry - comb,< divisor,0,L$largedivisor - sub %r0,divisor,%r1 ; clear cy as side-effect - ds %r0,%r1,%r0 - addc dividend,dividend,dividend - ds %r0,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,quotient - ds %r1,divisor,%r1 - bv 0(ret) - addc quotient,quotient,quotient -L$largedivisor - comclr,<< dividend,divisor,quotient - ldi 1,quotient - bv,n 0(ret) - .exit - .procend -#endif - - -#ifdef L_remU -#define dividend %r26 -#define divisor %r25 -#define quotient %r29 -#define tmp %r1 -#define ret %r31 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$remU -$$remU - .proc - .callinfo frame=0,no_calls - .entry - comb,< divisor,0,L$largedivisor - sub %r0,divisor,%r1 ; clear cy as side-effect - ds %r0,%r1,%r0 - addc dividend,dividend,dividend - ds %r0,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,quotient - ds %r1,divisor,%r1 - comclr,>= %r1,%r0,%r0 - addl %r1,divisor,%r1 - bv 0(ret) - copy %r1,quotient -L$largedivisor - sub,>>= dividend,divisor,quotient - copy dividend,quotient - bv,n 0(ret) - .exit - .procend -#endif - - -#ifdef L_divI -#define dividend %r26 -#define divisor %r25 -#define quotient %r29 -#define tmp %r1 -#define ret %r31 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divI -$$divI - .proc - .callinfo frame=0,no_calls - .entry - xor dividend,divisor,quotient ; result sign - comclr,>= divisor,%r0,%r0 ; get absolute values - sub %r0,divisor,divisor - comclr,>= dividend,%r0,%r0 - sub %r0,dividend,dividend - - comb,< divisor,0,L$largedivisor - sub %r0,divisor,%r1 ; clear cy as side-effect - ds %r0,%r1,%r0 - addc dividend,dividend,dividend - ds %r0,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - comclr,>= %r1,%r0,%r0 - addl %r1,divisor,%r1 - comclr,>= quotient,%r0,%r0 ; skip of no need to negate - sub %r0,dividend,dividend - bv 0(ret) - copy dividend,quotient -L$largedivisor - comclr,<< dividend,divisor,quotient - ldi 1,quotient - bv,n 0(ret) - .exit - .procend -#endif - - -#ifdef L_remI -#define dividend %r26 -#define divisor %r25 -#define quotient %r29 -#define tmp %r1 -#define ret %r31 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$remI -$$remI - .proc - .callinfo frame=0,no_calls - .entry - xor dividend,%r0,quotient ; result sign - comclr,>= divisor,%r0,%r0 ; get absolute values - sub %r0,divisor,divisor - comclr,>= dividend,%r0,%r0 - sub %r0,dividend,dividend - - comb,< divisor,0,L$largedivisor - sub %r0,divisor,%r1 ; clear cy as side-effect - ds %r0,%r1,%r0 - addc dividend,dividend,dividend - ds %r0,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - ds %r1,divisor,%r1 - addc dividend,dividend,dividend - comclr,>= %r1,%r0,%r0 - addl %r1,divisor,%r1 - comclr,>= quotient,%r0,%r0 ; skip of no need to negate - sub %r0,%r1,%r1 - bv 0(ret) - copy %r1,quotient -L$largedivisor - sub,>>= dividend,divisor,quotient - copy dividend,quotient - bv,n 0(ret) - .exit - .procend -#endif - - -#if defined (L_divU_3) && !defined (SMALL_LIB) -#undef L_divU_3 -#define dividend %r26 -#define divisor %r25 -#define tmp %r1 -#define result %r29 -#define ret %r31 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU_3 -$$divU_3 - .proc - .callinfo frame=0,no_calls - .entry - sh2add %r26,%r26,%r29 ; r29 = lo(101 x r) - shd %r0,%r26,30,%r1 ; r1 = hi(100 x r) - addc %r1,%r0,%r1 ; r1 = hi(101 x r) -; r in r1,,r29 - zdep %r29,27,28,%r25 ; r25 = lo(10000 x r) - add %r25,%r29,%r25 ; r25 = lo(10001 x r) - shd %r1,%r29,28,%r29 ; r29 = hi(10000 x r) - addc %r29,%r1,%r29 ; r29 = hi(10001 x r) -; r in r29,,r25 - zdep %r25,23,24,%r1 ; r1 = lo(100000000 x r) - add %r1,%r25,%r1 ; r1 = lo(100000001 x r) - shd %r29,%r25,24,%r25 ; r25 = hi(100000000 x r) - addc %r25,%r29,%r25 ; r25 = hi(100000001 x r) -; r in r25,,r1 - zdep %r1,15,16,%r29 - add %r29,%r1,%r29 - shd %r25,%r1,16,%r1 - addc %r1,%r25,%r1 -; r in r1,,r29 - sh1add %r29,%r26,%r0 ; r0 = lo(10 x r) + dividend - shd %r1,%r29,31,%r29 ; r29 = hi(10 x r) - addc %r29,%r0,%r29 - bv 0(ret) - extru %r29,30,31,result - .exit - .procend -#endif - - -#if defined (L_divU_5) && !defined (SMALL_LIB) -#undef L_divU_5 -#define dividend %r26 -#define divisor %r25 -#define tmp %r1 -#define result %r29 -#define ret %r31 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU_5 -$$divU_5 - .proc - .callinfo frame=0,no_calls - .entry - sh1add %r26,%r26,%r29 ; r29 = lo(11 x r) - shd %r0,%r26,31,%r1 ; r1 = hi(10 x r) - addc %r1,%r0,%r1 ; r1 = hi(11 x r) -; r in r1,,r29 - zdep %r29,27,28,%r25 ; r25 = lo(10000 x r) - add %r25,%r29,%r25 ; r25 = lo(10001 x r) - shd %r1,%r29,28,%r29 ; r29 = hi(10000 x r) - addc %r29,%r1,%r29 ; r29 = hi(10001 x r) -; r in r29,,r25 - zdep %r25,23,24,%r1 ; r1 = lo(100000000 x r) - add %r1,%r25,%r1 ; r1 = lo(100000001 x r) - shd %r29,%r25,24,%r25 ; r25 = hi(100000000 x r) - addc %r25,%r29,%r25 ; r25 = hi(100000001 x r) -; r in r25,,r1 - zdep %r1,15,16,%r29 - add %r29,%r1,%r29 - shd %r25,%r1,16,%r1 - addc %r1,%r25,%r1 -; r in r1,,r29 - sh2add %r29,%r26,%r0 ; r0 = lo(1000 x r) + dividend - shd %r1,%r29,30,%r29 ; r29 = hi(1000 x r) - addc %r29,%r0,%r29 - bv 0(ret) - extru %r29,29,30,result - .exit - .procend -#endif - - -#if defined (L_divU_6) && !defined (SMALL_LIB) -#undef L_divU_6 -#define dividend %r26 -#define divisor %r25 -#define tmp %r1 -#define result %r29 -#define ret %r31 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU_6 -$$divU_6 - .proc - .callinfo frame=0,no_calls - .entry - sh2add %r26,%r26,%r29 ; r29 = lo(101 x r) - shd %r0,%r26,30,%r1 ; r1 = hi(100 x r) - addc %r1,%r0,%r1 ; r1 = hi(101 x r) -; r in r1,,r29 - zdep %r29,27,28,%r25 ; r25 = lo(10000 x r) - add %r25,%r29,%r25 ; r25 = lo(10001 x r) - shd %r1,%r29,28,%r29 ; r29 = hi(10000 x r) - addc %r29,%r1,%r29 ; r29 = hi(10001 x r) -; r in r29,,r25 - zdep %r25,23,24,%r1 ; r1 = lo(100000000 x r) - add %r1,%r25,%r1 ; r1 = lo(100000001 x r) - shd %r29,%r25,24,%r25 ; r25 = hi(100000000 x r) - addc %r25,%r29,%r25 ; r25 = hi(100000001 x r) -; r in r25,,r1 - zdep %r1,15,16,%r29 - add %r29,%r1,%r29 - shd %r25,%r1,16,%r1 - addc %r1,%r25,%r1 -; r in r1,,r29 - sh1add %r29,%r26,%r0 ; r0 = lo(10 x r) + dividend - shd %r1,%r29,31,%r29 ; r29 = hi(10 x r) - addc %r29,%r0,%r29 - bv 0(ret) - extru %r29,29,30,result - .exit - .procend -#endif - - -#if defined (L_divU_9) && !defined (SMALL_LIB) -#undef L_divU_9 -#define dividend %r26 -#define divisor %r25 -#define tmp %r1 -#define result %r29 -#define ret %r31 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU_9 -$$divU_9 - .proc - .callinfo frame=0,no_calls - .entry - zdep %r26,28,29,%r29 - sub %r29,%r26,%r29 - shd 0,%r26,29,%r1 - subb %r1,0,%r1 /* 111 */ - - zdep %r29,25,26,%r25 - add %r25,%r29,%r25 - shd %r1,%r29,26,%r29 - addc %r29,%r1,%r29 /* 111000111 */ - - sh3add %r25,%r26,%r1 - shd %r29,%r25,29,%r25 - addc %r25,0,%r25 /* 111000111001 */ - - zdep %r1,16,17,%r29 - sub %r29,%r1,%r29 - shd %r25,%r1,17,%r1 - subb %r1,%r25,%r1 /* 111000111000111000111000111 */ - - sh3add %r29,%r26,%r0 - shd %r1,%r29,29,%r29 - addc %r29,0,%r29 /* 111000111000111000111000111001 */ - bv 0(ret) - extru %r29,30,31,result - .exit - .procend -#endif - - -#if defined (L_divU_10) && !defined (SMALL_LIB) -#undef L_divU_10 -#define dividend %r26 -#define divisor %r25 -#define tmp %r1 -#define result %r29 -#define ret %r31 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU_10 -$$divU_10 - .proc - .callinfo frame=0,no_calls - .entry - sh1add %r26,%r26,%r29 ; r29 = lo(11 x r) - shd %r0,%r26,31,%r1 ; r1 = hi(10 x r) - addc %r1,%r0,%r1 ; r1 = hi(11 x r) -; r in r1,,r29 - zdep %r29,27,28,%r25 ; r25 = lo(10000 x r) - add %r25,%r29,%r25 ; r25 = lo(10001 x r) - shd %r1,%r29,28,%r29 ; r29 = hi(10000 x r) - addc %r29,%r1,%r29 ; r29 = hi(10001 x r) -; r in r29,,r25 - zdep %r25,23,24,%r1 ; r1 = lo(100000000 x r) - add %r1,%r25,%r1 ; r1 = lo(100000001 x r) - shd %r29,%r25,24,%r25 ; r25 = hi(100000000 x r) - addc %r25,%r29,%r25 ; r25 = hi(100000001 x r) -; r in r25,,r1 - zdep %r1,15,16,%r29 - add %r29,%r1,%r29 - shd %r25,%r1,16,%r1 - addc %r1,%r25,%r1 -; r in r1,,r29 - sh2add %r29,%r26,%r0 ; r0 = lo(1000 x r) + dividend - shd %r1,%r29,30,%r29 ; r29 = hi(1000 x r) - addc %r29,%r0,%r29 - bv 0(ret) - extru %r29,28,29,result - .exit - .procend -#endif - - -#if defined (L_divU_12) && !defined (SMALL_LIB) -#undef L_divU_12 -#define dividend %r26 -#define divisor %r25 -#define tmp %r1 -#define result %r29 -#define ret %r31 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU_12 -$$divU_12 - .proc - .callinfo frame=0,no_calls - .entry - sh2add %r26,%r26,%r29 ; r29 = lo(101 x r) - shd %r0,%r26,30,%r1 ; r1 = hi(100 x r) - addc %r1,%r0,%r1 ; r1 = hi(101 x r) -; r in r1,,r29 - zdep %r29,27,28,%r25 ; r25 = lo(10000 x r) - add %r25,%r29,%r25 ; r25 = lo(10001 x r) - shd %r1,%r29,28,%r29 ; r29 = hi(10000 x r) - addc %r29,%r1,%r29 ; r29 = hi(10001 x r) -; r in r29,,r25 - zdep %r25,23,24,%r1 ; r1 = lo(100000000 x r) - add %r1,%r25,%r1 ; r1 = lo(100000001 x r) - shd %r29,%r25,24,%r25 ; r25 = hi(100000000 x r) - addc %r25,%r29,%r25 ; r25 = hi(100000001 x r) -; r in r25,,r1 - zdep %r1,15,16,%r29 - add %r29,%r1,%r29 - shd %r25,%r1,16,%r1 - addc %r1,%r25,%r1 -; r in r1,,r29 - sh1add %r29,%r26,%r0 ; r0 = lo(10 x r) + dividend - shd %r1,%r29,31,%r29 ; r29 = hi(10 x r) - addc %r29,%r0,%r29 - bv 0(ret) - extru %r29,28,29,result - .exit - .procend -#endif - - -#ifdef L_divU_3 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU_3 -$$divU_3 - .proc - .callinfo frame=0,no_calls - .entry - b $$divU - ldi 3,%r25 - .exit - .procend - .import $$divU,MILLICODE -#endif - -#ifdef L_divU_5 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU_5 -$$divU_5 - .proc - .callinfo frame=0,no_calls - .entry - b $$divU - ldi 5,%r25 - .exit - .procend - .import $$divU,MILLICODE -#endif - -#ifdef L_divU_6 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU_6 -$$divU_6 - .proc - .callinfo frame=0,no_calls - .entry - b $$divU - ldi 6,%r25 - .exit - .procend - .import $$divU,MILLICODE -#endif - -#ifdef L_divU_7 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU_7 -$$divU_7 - .proc - .callinfo frame=0,no_calls - .entry - b $$divU - ldi 7,%r25 - .exit - .procend - .import $$divU,MILLICODE -#endif - -#ifdef L_divU_9 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU_9 -$$divU_9 - .proc - .callinfo frame=0,no_calls - .entry - b $$divU - ldi 9,%r25 - .exit - .procend - .import $$divU,MILLICODE -#endif - -#ifdef L_divU_10 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU_10 -$$divU_10 - .proc - .callinfo frame=0,no_calls - .entry - b $$divU - ldi 10,%r25 - .exit - .procend - .import $$divU,MILLICODE -#endif - -#ifdef L_divU_12 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU_12 -$$divU_12 - .proc - .callinfo frame=0,no_calls - .entry - b $$divU - ldi 12,%r25 - .exit - .procend - .import $$divU,MILLICODE -#endif - -#ifdef L_divU_14 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU_14 -$$divU_14 - .proc - .callinfo frame=0,no_calls - .entry - b $$divU - ldi 14,%r25 - .exit - .procend - .import $$divU,MILLICODE -#endif - -#ifdef L_divU_15 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divU_15 -$$divU_15 - .proc - .callinfo frame=0,no_calls - .entry - b $$divU - ldi 15,%r25 - .exit - .procend - .import $$divU,MILLICODE -#endif - -#ifdef L_divI_3 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divI_3 -$$divI_3 - .proc - .callinfo frame=0,no_calls - .entry - b $$divI - ldi 3,%r25 - .exit - .procend - .import $$divI,MILLICODE -#endif - -#ifdef L_divI_5 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divI_5 -$$divI_5 - .proc - .callinfo frame=0,no_calls - .entry - b $$divI - ldi 5,%r25 - .exit - .procend - .import $$divI,MILLICODE -#endif - -#ifdef L_divI_6 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divI_6 -$$divI_6 - .proc - .callinfo frame=0,no_calls - .entry - b $$divI - ldi 6,%r25 - .exit - .procend - .import $$divI,MILLICODE -#endif - -#ifdef L_divI_7 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divI_7 -$$divI_7 - .proc - .callinfo frame=0,no_calls - .entry - b $$divI - ldi 7,%r25 - .exit - .procend - .import $$divI,MILLICODE -#endif - -#ifdef L_divI_9 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divI_9 -$$divI_9 - .proc - .callinfo frame=0,no_calls - .entry - b $$divI - ldi 9,%r25 - .exit - .procend - .import $$divI,MILLICODE -#endif - -#ifdef L_divI_10 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divI_10 -$$divI_10 - .proc - .callinfo frame=0,no_calls - .entry - b $$divI - ldi 10,%r25 - .exit - .procend - .import $$divI,MILLICODE -#endif - -#ifdef L_divI_12 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divI_12 -$$divI_12 - .proc - .callinfo frame=0,no_calls - .entry - b $$divI - ldi 12,%r25 - .exit - .procend - .import $$divI,MILLICODE -#endif - -#ifdef L_divI_14 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divI_14 -$$divI_14 - .proc - .callinfo frame=0,no_calls - .entry - b $$divI - ldi 14,%r25 - .exit - .procend - .import $$divI,MILLICODE -#endif - -#ifdef L_divI_15 - .space $TEXT$ - .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 - .align 4 - .export $$divI_15 -$$divI_15 - .proc - .callinfo frame=0,no_calls - .entry - b $$divI - ldi 15,%r25 - .exit - .procend - .import $$divI,MILLICODE -#endif diff --git a/gcc/config/pa/lib2funcs.asm b/gcc/config/pa/lib2funcs.asm deleted file mode 100755 index cf57cbb..0000000 --- a/gcc/config/pa/lib2funcs.asm +++ /dev/null @@ -1,74 +0,0 @@ -; Subroutines for calling unbound dynamic functions from within GDB for HPPA. -; Subroutines for out of line prologues and epilogues on for the HPPA -; Copyright (C) 1994, 1995, 1996 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. - -; 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. - -; 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.) - -; 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. - - .SPACE $PRIVATE$ - .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31 - .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82 - .SPACE $TEXT$ - .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44 - .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY - .SUBSPA $MILLICODE$,QUAD=0,ALIGN=8,ACCESS=44,SORT=8 - - .IMPORT $$dyncall,MILLICODE -; gcc_compiled.: - .SPACE $TEXT$ - .SUBSPA $CODE$ - -; Simply call with the address of the desired import stub in %r22 and -; arguments in the normal place (%r26-%r23 and stack slots). -; - .align 4 - .EXPORT __gcc_plt_call,ENTRY,PRIV_LEV=3,RTNVAL=GR -__gcc_plt_call - .PROC - .CALLINFO - .ENTRY - ; Our return address comes in %r31, not %r2! - stw %r31,-8(0,%r30) - - ; An inline version of dyncall so we don't have to worry - ; about long calls to millicode, PIC and other complexities. - bb,>=,n %r22,30,L$foo - depi 0,31,2,%r22 - ldw 4(%r22),%r19 - ldw 0(%r22),%r22 -L$foo - ldsid (%r22),%r1 - mtsp %r1,%sr0 - ble 0(%sr0,%r22) - copy %r31,%r2 - ldw -8(0,%r30),%r2 - - ; We're going to be returning to a stack address, so we - ; need to do an intra-space return. - ldsid (%rp),%r1 - mtsp %r1,%sr0 - be,n 0(%sr0,%rp) - .EXIT - .PROCEND diff --git a/gcc/config/pa/pa-gas.h b/gcc/config/pa/pa-gas.h deleted file mode 100755 index 4106b70..0000000 --- a/gcc/config/pa/pa-gas.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Definitions of target machine for GNU compiler, for HP-UX using GNU as. - Copyright (C) 1996 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. - -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. */ - -#undef TARGET_DEFAULT -#define TARGET_DEFAULT 0x88 /* TARGET_GAS + TARGET_JUMP_IN_DELAY */ diff --git a/gcc/config/pa/pa-hiux.h b/gcc/config/pa/pa-hiux.h deleted file mode 100755 index f4be95b..0000000 --- a/gcc/config/pa/pa-hiux.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Definitions of target machine for GNU compiler, for HI-UX. - Copyright (C) 1993, 1995, 1996 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. - -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. */ - -/* HIUX is just a HPUX variant. We can simply use the HPUX configuration - for just about everything. */ - -/* Predefines are the one noteworthy difference between HPUX and HIUX. */ -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dhppa -DPWB -Dunix -D__H3050R -D__H3050RX -Asystem(unix) -Asystem(hiux) -Acpu(hppa) -Amachine(hppa)" diff --git a/gcc/config/pa/pa-hpux.h b/gcc/config/pa/pa-hpux.h deleted file mode 100755 index e001ebe..0000000 --- a/gcc/config/pa/pa-hpux.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Definitions of target machine for GNU compiler, for HP-UX. - Copyright (C) 1991, 1995, 1996 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. - -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. */ - -#undef TARGET_DEFAULT -#define TARGET_DEFAULT 0 - -/* Make GCC agree with types.h. */ -#undef SIZE_TYPE -#undef PTRDIFF_TYPE - -#define SIZE_TYPE "unsigned int" -#define PTRDIFF_TYPE "int" - -/* Like the default, except no -lg. */ -#undef LIB_SPEC -#define LIB_SPEC "%{!shared:%{!p:%{!pg:-lc}}%{p: -L/lib/libp/ -lc}%{pg: -L/lib/libp/ -lc}}" - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -DPWB -Dhpux -Dunix -Asystem(unix) -Asystem(hpux) -Acpu(hppa) -Amachine(hppa)" - -#undef LINK_SPEC -#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1) -#define LINK_SPEC \ - "%{!mpa-risc-1-0:%{!shared:-L/lib/pa1.1 -L/usr/lib/pa1.1 }}%{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{g*:-a archive} %{shared:-b}" -#else -#define LINK_SPEC \ - "%{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{g*:-a archive} %{shared:-b}" -#endif - -/* hpux8 and later have C++ compatible include files, so do not - pretend they are `extern "C"'. */ -#define NO_IMPLICIT_EXTERN_C diff --git a/gcc/config/pa/pa-hpux10.h b/gcc/config/pa/pa-hpux10.h deleted file mode 100755 index e00c107..0000000 --- a/gcc/config/pa/pa-hpux10.h +++ /dev/null @@ -1,89 +0,0 @@ -/* Definitions of target machine for GNU compiler, for HP PA-RISC 1.1 - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - Contributed by Tim Moore (moore@defmacro.cs.utah.edu) - -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. */ - -/* We can debug dynamically linked executables on hpux9; we also want - dereferencing of a NULL pointer to cause a SEGV. */ -#undef LINK_SPEC -#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1) -#define LINK_SPEC \ - "%{!mpa-risc-1-0:%{!shared:-L/lib/pa1.1 -L/usr/lib/pa1.1 }} -z %{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{shared:-b}" -#else -#define LINK_SPEC \ - "-z %{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{shared:-b}" -#endif - -/* Like the default, except no -lg. */ -#undef LIB_SPEC -#define LIB_SPEC \ - "%{!shared:\ - %{!p:\ - %{!pg:\ - %{!threads:-lc}\ - %{threads:-lcma -lc_r}}\ - %{p: -L/lib/libp/ -lc}\ - %{pg: -L/lib/libp/ -lc}}}" - -/* The hpux10 assembler requires a .LEVEL pseudo-op at the start of - the assembly file. */ -#undef ASM_FILE_START -#define ASM_FILE_START(FILE) \ -do { \ - /* CYGNUS LOCAL pa8000/law */ \ - if (TARGET_PARISC_2_0) \ - fputs("\t.LEVEL 2.0\n", FILE); \ - else if (TARGET_SNAKE) \ - fputs("\t.LEVEL 1.1\n", FILE); \ - else \ - fputs("\t.LEVEL 1.0\n", FILE); \ - /* END CYGNUS LOCAL */ \ - fputs ("\t.SPACE $PRIVATE$\n\ -\t.SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31\n\ -\t.SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82\n\ -\t.SPACE $TEXT$\n\ -\t.SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44\n\ -\t.SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n\ -\t.IMPORT $global$,DATA\n\ -\t.IMPORT $$dyncall,MILLICODE\n", FILE);\ - if (profile_flag)\ - fprintf (FILE, "\t.IMPORT _mcount, CODE\n");\ - if (write_symbols != NO_DEBUG) \ - output_file_directive ((FILE), main_input_filename); \ - } while (0) - -/* Under hpux10, the normal location of the `ld' and `as' programs is the - /usr/ccs/bin directory. */ - -#ifndef CROSS_COMPILE -#undef MD_EXEC_PREFIX -#define MD_EXEC_PREFIX "/usr/ccs/bin/" -#endif - -/* Under hpux10, the normal location of the various *crt*.o files is the - /usr/ccs/lib directory. */ - -#ifndef CROSS_COMPILE -#undef MD_STARTFILE_PREFIX -#define MD_STARTFILE_PREFIX "/usr/ccs/lib/" -#endif - -/* hpux10 has the new HP assembler. It's still lousy, but it's a whole lot - better than the assembler shipped with older versions of hpux. */ -#define NEW_HP_ASSEMBLER diff --git a/gcc/config/pa/pa-hpux11.h b/gcc/config/pa/pa-hpux11.h deleted file mode 100755 index 2959c5c..0000000 --- a/gcc/config/pa/pa-hpux11.h +++ /dev/null @@ -1,98 +0,0 @@ -/* CYGNUS LOCAL entire file hpux11/law */ -/* Definitions of target machine for GNU compiler, for HP PA-RISC 1.1 - Copyright (C) 1998 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. - -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. */ - -/* We can debug dynamically linked executables on hpux11; we also - want dereferencing of a NULL pointer to cause a SEGV. */ -#undef LINK_SPEC -#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1) -#define LINK_SPEC \ - "%{!mpa-risc-1-0:%{!shared:-L/lib/pa1.1 -L/usr/lib/pa1.1 }} -z %{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{shared:-b}" -#else -#define LINK_SPEC \ - "-z %{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{shared:-b}" -#endif - -/* Like the default, except no -lg. */ -#undef LIB_SPEC -#define LIB_SPEC \ - "%{!shared:\ - %{!p:\ - %{!pg:\ - %{!threads:-lc}\ - %{threads:-lcma -lc_r}}\ - %{p: -L/lib/libp/ -lc}\ - %{pg: -L/lib/libp/ -lc}}}" - -/* The hpux11 assembler requires a .LEVEL pseudo-op at the start of the - assembly file. */ -#undef ASM_FILE_START -#define ASM_FILE_START(FILE) \ -do { \ - /* CYGNUS LOCAL pa8000/law */ \ - if (TARGET_PARISC_2_0) \ - fputs("\t.LEVEL 2.0\n", FILE); \ - else if (TARGET_SNAKE) \ - fputs("\t.LEVEL 1.1\n", FILE); \ - else \ - fputs("\t.LEVEL 1.0\n", FILE); \ - /* END CYGNUS LOCAL */ \ - fputs ("\t.SPACE $PRIVATE$\n\ -\t.SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31\n\ -\t.SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82\n\ -\t.SPACE $TEXT$\n\ -\t.SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44\n\ -\t.SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n\ -\t.IMPORT $global$,DATA\n\ -\t.IMPORT $$dyncall,MILLICODE\n", FILE);\ - if (profile_flag)\ - fprintf (FILE, "\t.IMPORT _mcount, CODE\n");\ - if (write_symbols != NO_DEBUG) \ - output_file_directive ((FILE), main_input_filename); \ - } while (0) - -/* Under hpux11, the normal location of the `ld' and `as' programs is the - /usr/ccs/bin directory. */ - -#ifndef CROSS_COMPILE -#undef MD_EXEC_PREFIX -#define MD_EXEC_PREFIX "/usr/ccs/bin/" -#endif - -/* Under hpux11 the normal location of the various *crt*.o files is the - /usr/ccs/lib directory. */ - -#ifndef CROSS_COMPILE -#undef MD_STARTFILE_PREFIX -#define MD_STARTFILE_PREFIX "/usr/ccs/lib/" -#endif - -/* hpux11 has the new HP assembler. It's still lousy, but it's a whole lot - better than the assembler shipped with older versions of hpux. */ -#define NEW_HP_ASSEMBLER - -/* Make GCC agree with types.h. */ -#undef SIZE_TYPE -#undef PTRDIFF_TYPE - -#define SIZE_TYPE "long unsigned int" -#define PTRDIFF_TYPE "long int" - -/* END CYGNUS LOCAL */ diff --git a/gcc/config/pa/pa-hpux7.h b/gcc/config/pa/pa-hpux7.h deleted file mode 100755 index dc75ec2..0000000 --- a/gcc/config/pa/pa-hpux7.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Definitions of target machine for GNU compiler, for HP-UX. - Copyright (C) 1991, 1995, 1996 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. - -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. */ - -#ifndef TARGET_DEFAULT -#define TARGET_DEFAULT 0 -#endif - -/* Make GCC agree with types.h. */ -#undef SIZE_TYPE -#undef PTRDIFF_TYPE - -#define SIZE_TYPE "unsigned int" -#define PTRDIFF_TYPE "int" - -/* Like the default, except no -lg. */ -#undef LIB_SPEC -#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p: -L/lib/libp/ -lc}%{pg: -L/lib/libp/ -lc}" - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -DPWB -Dhpux -Dunix -Asystem(unix) -Asystem(hpux) -Acpu(hppa) -Amachine(hppa)" diff --git a/gcc/config/pa/pa-hpux9.h b/gcc/config/pa/pa-hpux9.h deleted file mode 100755 index 8d039d2..0000000 --- a/gcc/config/pa/pa-hpux9.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Definitions of target machine for GNU compiler, for HP PA-RISC 1.1 - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - Contributed by Tim Moore (moore@defmacro.cs.utah.edu) - -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. */ - -/* We can debug dynamically linked executables on hpux9; we also want - dereferencing of a NULL pointer to cause a SEGV. */ -#undef LINK_SPEC -#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1) -#define LINK_SPEC \ - "%{!mpa-risc-1-0:%{!shared:-L/lib/pa1.1 -L/usr/lib/pa1.1 }} -z %{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{shared:-b}" -#else -#define LINK_SPEC \ - "-z %{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{shared:-b}" -#endif diff --git a/gcc/config/pa/pa-oldas.h b/gcc/config/pa/pa-oldas.h deleted file mode 100755 index 8ff741f..0000000 --- a/gcc/config/pa/pa-oldas.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Definitions of target machine for GNU compiler, for HP PA-RISC 1.1 - Copyright (C) 1991, 1996 Free Software Foundation, Inc. - Contributed by Tim Moore (moore@defmacro.cs.utah.edu) - -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. */ - -#define HP_FP_ARG_DESCRIPTOR_REVERSED diff --git a/gcc/config/pa/pa-osf.h b/gcc/config/pa/pa-osf.h deleted file mode 100755 index 047d20e..0000000 --- a/gcc/config/pa/pa-osf.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Definitions of target machine for GNU compiler, for HP PA-RISC 1.1 - Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc. - Contributed by Tim Moore (moore@defmacro.cs.utah.edu) - -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. */ - -#undef CPP_PREDEFINES -#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1) -#define CPP_PREDEFINES "-Dhppa -Dunix -Dhp9000 -Dspectrum -DREVARGV -Dhp700 -DHP700 -Dparisc -D__pa_risc -DPARISC -DBYTE_MSF -DBIT_MSF -Asystem(unix) -Asystem(mach) -Acpu(hppa) -Amachine(hppa)" -#else -#define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -Dunix -Dhp9000 -Dhp800 -Dspectrum -DREVARGV -Dparisc -D__pa_risc -DPARISC -DBYTE_MSF -DBIT_MSF -Asystem(unix) -Asystem(mach) -Acpu(hppa) -Amachine(hppa)" -#endif - -/* Don't default to pcc-struct-return, because gcc is the only compiler, and - we want to retain compatibility with older gcc versions. */ -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/* OSF1 on the PA still uses 16bit wchar_t. */ -#undef WCHAR_TYPE -#undef WCHAR_TYPE_SIZE - -#define WCHAR_TYPE "short unsigned int" -#define WCHAR_TYPE_SIZE 16 - -/* OSF1 wants to be different and use unsigned long as size_t. */ -#undef SIZE_TYPE -#define SIZE_TYPE "long unsigned int" diff --git a/gcc/config/pa/pa-pro-end.h b/gcc/config/pa/pa-pro-end.h deleted file mode 100755 index de88036..0000000 --- a/gcc/config/pa/pa-pro-end.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Definitions of target machine for GNU compiler, for PRO. - 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. - -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. */ - -/* Make GCC agree with types.h. */ -#undef SIZE_TYPE -#undef PTRDIFF_TYPE - -#define SIZE_TYPE "unsigned int" -#define PTRDIFF_TYPE "int" - -/* Like the default, except no -lg. */ -#undef LIB_SPEC -#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p: -L/lib/libp/ -lc}%{pg: -L/lib/libp/ -lc}" - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dhppa -DPWB -Acpu(hppa) -Amachine(hppa)" - -/* hpux8 and later have C++ compatible include files, so do not - pretend they are `extern "C"'. */ -#define NO_IMPLICIT_EXTERN_C - -/* We don't want a crt0.o to get linked in automatically, we want the - linker script to pull it in. - */ -#define STARTFILE_SPEC "" diff --git a/gcc/config/pa/pa-pro.h b/gcc/config/pa/pa-pro.h deleted file mode 100755 index 2ec832b..0000000 --- a/gcc/config/pa/pa-pro.h +++ /dev/null @@ -1,79 +0,0 @@ -/* Definitions of target machine for GNU compiler, for PRO. - Copyright (C) 1994, 1995, 1996 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. - -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. */ - -/* Global constructor and destructor support. */ -/* Define the pseudo-ops used to switch to the .ctors and .dtors sections. - - Note that we want to give these sections the SHF_WRITE attribute - because these sections will actually contain data (i.e. tables of - addresses of functions in the current root executable or shared library - file) and, in the case of a shared library, the relocatable addresses - will have to be properly resolved/relocated (and then written into) by - the dynamic linker when it actually attaches the given shared library - to the executing process. */ - -#define CTORS_SECTION_ASM_OP "\t.section\t\".ctors\",#alloc,#write" -#define DTORS_SECTION_ASM_OP "\t.section\t\".dtors\",#alloc,#write" - -#define CTORS_SECTION_FUNCTION \ -void \ -ctors_section () \ -{ \ - if (in_section != in_ctors) \ - { \ - fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ - in_section = in_ctors; \ - } \ -} - -#define DTORS_SECTION_FUNCTION \ -void \ -dtors_section () \ -{ \ - if (in_section != in_dtors) \ - { \ - fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ - in_section = in_dtors; \ - } \ -} - - -/* A C statement (sans semicolon) to output an element in the table of - global destructors. */ -#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ - do { \ - dtors_section (); \ - fputs ("\t.word\t ", FILE); \ - assemble_name (FILE, NAME); \ - fputs ("\n", FILE); \ - } while (0) - -/* A C statement (sans semicolon) to output an element in the table of - global constructors. */ -#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ - do { \ - ctors_section (); \ - fputs ("\t.word\t ", FILE); \ - assemble_name (FILE, NAME); \ - fputs ("\n", FILE); \ - } while (0) - -/* JUMP_IN_DELAY + PORTABLE_RUNTIME + GAS + NO_SPACE_REGS + SOFT_FLOAT */ -#define TARGET_DEFAULT (4 + 8 + 64 + 128 + 256) diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c deleted file mode 100755 index de7f698..0000000 --- a/gcc/config/pa/pa.c +++ /dev/null @@ -1,6491 +0,0 @@ -/* Subroutines for insn-output.c for HPPA. - Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc. - Contributed by Tim Moore (moore@cs.utah.edu), based on sparc.c - -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 "config.h" -#include "system.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 "tree.h" -#include "reload.h" -#include "c-tree.h" -#include "expr.h" -#include "obstack.h" -#include "toplev.h" - -static void restore_unscaled_index_insn_codes PROTO((rtx)); -static void record_unscaled_index_insn_codes PROTO((rtx)); -static void pa_combine_instructions PROTO((rtx)); -static int pa_can_combine_p PROTO((rtx, rtx, rtx, int, rtx, rtx, rtx)); -static int forward_branch_p PROTO((rtx)); -static int shadd_constant_p PROTO((int)); - -/* Save the operands last given to a compare for use when we - generate a scc or bcc insn. */ - -rtx hppa_compare_op0, hppa_compare_op1; -enum cmp_type hppa_branch_type; - -/* Which cpu we are scheduling for. */ -enum processor_type pa_cpu; - -/* String to hold which cpu we are scheduling for. */ -char *pa_cpu_string; - -/* Set by the FUNCTION_PROFILER macro. */ -int hp_profile_labelno; - -/* Counts for the number of callee-saved general and floating point - registers which were saved by the current function's prologue. */ -static int gr_saved, fr_saved; - -/* Whether or not the current function uses an out-of-line prologue - and epilogue. */ -static int out_of_line_prologue_epilogue; - -static rtx find_addr_reg (); - -/* Keep track of the number of bytes we have output in the CODE subspaces - during this compilation so we'll know when to emit inline long-calls. */ - -unsigned int total_code_bytes; - -/* Variables to handle plabels that we discover are necessary at assembly - output time. They are output after the current function. */ - -struct deferred_plabel -{ - rtx internal_label; - char *name; -} *deferred_plabels = 0; -int n_deferred_plabels = 0; - -/* Array indexed by INSN_UIDs holding the INSN_CODE of an insn which - uses an unscaled indexed address before delay slot scheduling. */ -static int *unscaled_index_insn_codes; - -/* Upper bound for the array. */ -static int max_unscaled_index_insn_codes_uid; - -void -override_options () -{ - /* Default to 7100 scheduling. If the 7100LC scheduling ever - gets reasonably tuned, it should be the default since that - what most PAs sold now are. */ - if (pa_cpu_string == NULL - || ! strcmp (pa_cpu_string, "7100")) - { - pa_cpu_string = "7100"; - pa_cpu = PROCESSOR_7100; - } - else if (! strcmp (pa_cpu_string, "700")) - { - pa_cpu_string = "700"; - pa_cpu = PROCESSOR_700; - } - else if (! strcmp (pa_cpu_string, "7100LC")) - { - pa_cpu_string = "7100LC"; - pa_cpu = PROCESSOR_7100LC; - } - else if (! strcmp (pa_cpu_string, "7200")) - { - pa_cpu_string = "7200"; - pa_cpu = PROCESSOR_7200; - } - /* CYGNUS LOCAL PA8000/law */ - else if (! strcmp (pa_cpu_string, "8000")) - { - pa_cpu_string = "8000"; - pa_cpu = PROCESSOR_8000; - } - else - { - warning ("Unknown -mschedule= option (%s).\nValid options are 700, 7100 and 7100LC, 7200 and 8000\n", pa_cpu_string); - } - /* END CYGNUS LOCAL */ - - if (flag_pic && TARGET_PORTABLE_RUNTIME) - { - warning ("PIC code generation is not supported in the portable runtime model\n"); - } - - if (flag_pic && (TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS)) - { - warning ("PIC code generation is not compatible with fast indirect calls\n"); - } - - if (flag_pic && profile_flag) - { - warning ("PIC code generation is not compatible with profiling\n"); - } - - if (TARGET_SPACE && (flag_pic || profile_flag)) - { - warning ("Out of line entry/exit sequences are not compatible\n"); - warning ("with PIC or profiling\n"); - } - - if (! TARGET_GAS && write_symbols != NO_DEBUG) - { - warning ("-g is only supported when using GAS on this processor,"); - warning ("-g option disabled."); - write_symbols = NO_DEBUG; - } -} - - -/* Return non-zero only if OP is a register of mode MODE, - or CONST0_RTX. */ -int -reg_or_0_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (op == CONST0_RTX (mode) || register_operand (op, mode)); -} - -/* Return non-zero if OP is suitable for use in a call to a named - function. - - (???) For 2.5 try to eliminate either call_operand_address or - function_label_operand, they perform very similar functions. */ -int -call_operand_address (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (CONSTANT_P (op) && ! TARGET_PORTABLE_RUNTIME); -} - -/* Return 1 if X contains a symbolic expression. We know these - expressions will have one of a few well defined forms, so - we need only check those forms. */ -int -symbolic_expression_p (x) - register rtx x; -{ - - /* Strip off any HIGH. */ - if (GET_CODE (x) == HIGH) - x = XEXP (x, 0); - - return (symbolic_operand (x, VOIDmode)); -} - -int -symbolic_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - switch (GET_CODE (op)) - { - case SYMBOL_REF: - case LABEL_REF: - return 1; - case CONST: - op = XEXP (op, 0); - return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF - || GET_CODE (XEXP (op, 0)) == LABEL_REF) - && GET_CODE (XEXP (op, 1)) == CONST_INT); - default: - return 0; - } -} - -/* Return truth value of statement that OP is a symbolic memory - operand of mode MODE. */ - -int -symbolic_memory_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST - || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF); -} - -/* Return 1 if the operand is either a register or a memory operand that is - not symbolic. */ - -int -reg_or_nonsymb_mem_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (register_operand (op, mode)) - return 1; - - if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode)) - return 1; - - return 0; -} - -/* Return 1 if the operand is either a register, zero, or a memory operand - that is not symbolic. */ - -int -reg_or_0_or_nonsymb_mem_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (register_operand (op, mode)) - return 1; - - if (op == CONST0_RTX (mode)) - return 1; - - if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode)) - return 1; - - return 0; -} - -/* Accept any constant that can be moved in one instructions into a - general register. */ -int -cint_ok_for_move (intval) - HOST_WIDE_INT intval; -{ - /* OK if ldo, ldil, or zdepi, can be used. */ - return (VAL_14_BITS_P (intval) || (intval & 0x7ff) == 0 - || zdepi_cint_p (intval)); -} - -/* Accept anything that can be moved in one instruction into a general - register. */ -int -move_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (register_operand (op, mode)) - return 1; - - if (GET_CODE (op) == CONSTANT_P_RTX) - return 1; - - if (GET_CODE (op) == CONST_INT) - return cint_ok_for_move (INTVAL (op)); - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - if (GET_CODE (op) != MEM) - return 0; - - op = XEXP (op, 0); - if (GET_CODE (op) == LO_SUM) - return (register_operand (XEXP (op, 0), Pmode) - && CONSTANT_P (XEXP (op, 1))); - - /* Since move_operand is only used for source operands, we can always - allow scaled indexing! */ - if (! TARGET_DISABLE_INDEXING - && GET_CODE (op) == PLUS - && ((GET_CODE (XEXP (op, 0)) == MULT - && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG - && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT - && INTVAL (XEXP (XEXP (op, 0), 1)) == GET_MODE_SIZE (mode) - && GET_CODE (XEXP (op, 1)) == REG) - || (GET_CODE (XEXP (op, 1)) == MULT - &&GET_CODE (XEXP (XEXP (op, 1), 0)) == REG - && GET_CODE (XEXP (XEXP (op, 1), 1)) == CONST_INT - && INTVAL (XEXP (XEXP (op, 1), 1)) == GET_MODE_SIZE (mode) - && GET_CODE (XEXP (op, 0)) == REG))) - return 1; - - return memory_address_p (mode, op); -} - -/* Accept REG and any CONST_INT that can be moved in one instruction into a - general register. */ -int -reg_or_cint_move_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (register_operand (op, mode)) - return 1; - - if (GET_CODE (op) == CONST_INT) - return cint_ok_for_move (INTVAL (op)); - - return 0; -} - -int -pic_label_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (!flag_pic) - return 0; - - switch (GET_CODE (op)) - { - case LABEL_REF: - return 1; - case CONST: - op = XEXP (op, 0); - return (GET_CODE (XEXP (op, 0)) == LABEL_REF - && GET_CODE (XEXP (op, 1)) == CONST_INT); - default: - return 0; - } -} - -int -fp_reg_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return reg_renumber && FP_REG_P (op); -} - - - -/* Return truth value of whether OP can be used as an operand in a - three operand arithmetic insn that accepts registers of mode MODE - or 14-bit signed integers. */ -int -arith_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_INT && INT_14_BITS (op))); -} - -/* Return truth value of whether OP can be used as an operand in a - three operand arithmetic insn that accepts registers of mode MODE - or 11-bit signed integers. */ -int -arith11_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_INT && INT_11_BITS (op))); -} - -/* A constant integer suitable for use in a PRE_MODIFY memory - reference. */ -int -pre_cint_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == CONST_INT - && INTVAL (op) >= -0x2000 && INTVAL (op) < 0x10); -} - -/* A constant integer suitable for use in a POST_MODIFY memory - reference. */ -int -post_cint_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == CONST_INT - && INTVAL (op) < 0x2000 && INTVAL (op) >= -0x10); -} - -int -arith_double_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_DOUBLE - && GET_MODE (op) == mode - && VAL_14_BITS_P (CONST_DOUBLE_LOW (op)) - && ((CONST_DOUBLE_HIGH (op) >= 0) - == ((CONST_DOUBLE_LOW (op) & 0x1000) == 0)))); -} - -/* Return truth value of whether OP is a integer which fits the - range constraining immediate operands in three-address insns, or - is an integer register. */ - -int -ireg_or_int5_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return ((GET_CODE (op) == CONST_INT && INT_5_BITS (op)) - || (GET_CODE (op) == REG && REGNO (op) > 0 && REGNO (op) < 32)); -} - -/* Return truth value of whether OP is a integer which fits the - range constraining immediate operands in three-address insns. */ - -int -int5_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == CONST_INT && INT_5_BITS (op)); -} - -int -uint5_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == CONST_INT && INT_U5_BITS (op)); -} - -int -int11_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == CONST_INT && INT_11_BITS (op)); -} - -int -uint32_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ -#if HOST_BITS_PER_WIDE_INT > 32 - /* All allowed constants will fit a CONST_INT. */ - return (GET_CODE (op) == CONST_INT - && (INTVAL (op) >= 0 && INTVAL (op) < 0x100000000L)); -#else - return (GET_CODE (op) == CONST_INT - || (GET_CODE (op) == CONST_DOUBLE - && CONST_DOUBLE_HIGH (op) == 0)); -#endif -} - -int -arith5_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return register_operand (op, mode) || int5_operand (op, mode); -} - -/* True iff zdepi can be used to generate this CONST_INT. */ -int -zdepi_cint_p (x) - unsigned HOST_WIDE_INT x; -{ - unsigned HOST_WIDE_INT lsb_mask, t; - - /* This might not be obvious, but it's at least fast. - This function is critical; we don't have the time loops would take. */ - lsb_mask = x & -x; - t = ((x >> 4) + lsb_mask) & ~(lsb_mask - 1); - /* Return true iff t is a power of two. */ - return ((t & (t - 1)) == 0); -} - -/* True iff depi or extru can be used to compute (reg & mask). - Accept bit pattern like these: - 0....01....1 - 1....10....0 - 1..10..01..1 */ -int -and_mask_p (mask) - unsigned HOST_WIDE_INT mask; -{ - mask = ~mask; - mask += mask & -mask; - return (mask & (mask - 1)) == 0; -} - -/* True iff depi or extru can be used to compute (reg & OP). */ -int -and_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_INT && and_mask_p (INTVAL (op)))); -} - -/* True iff depi can be used to compute (reg | MASK). */ -int -ior_mask_p (mask) - unsigned HOST_WIDE_INT mask; -{ - mask += mask & -mask; - return (mask & (mask - 1)) == 0; -} - -/* True iff depi can be used to compute (reg | OP). */ -int -ior_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == CONST_INT && ior_mask_p (INTVAL (op))); -} - -int -lhs_lshift_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return register_operand (op, mode) || lhs_lshift_cint_operand (op, mode); -} - -/* True iff OP is a CONST_INT of the forms 0...0xxxx or 0...01...1xxxx. - Such values can be the left hand side x in (x << r), using the zvdepi - instruction. */ -int -lhs_lshift_cint_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - unsigned HOST_WIDE_INT x; - if (GET_CODE (op) != CONST_INT) - return 0; - x = INTVAL (op) >> 4; - return (x & (x + 1)) == 0; -} - -int -arith32_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return register_operand (op, mode) || GET_CODE (op) == CONST_INT; -} - -int -pc_or_label_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF); -} - -/* Legitimize PIC addresses. If the address is already - position-independent, we return ORIG. Newly generated - position-independent addresses go to REG. If we need more - than one register, we lose. */ - -rtx -legitimize_pic_address (orig, mode, reg) - rtx orig, reg; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - rtx pic_ref = orig; - - /* Labels need special handling. */ - if (pic_label_operand (orig)) - { - emit_insn (gen_pic_load_label (reg, orig)); - current_function_uses_pic_offset_table = 1; - return reg; - } - if (GET_CODE (orig) == SYMBOL_REF) - { - if (reg == 0) - abort (); - - if (flag_pic == 2) - { - emit_insn (gen_pic2_highpart (reg, pic_offset_table_rtx, orig)); - pic_ref - = gen_rtx_MEM (Pmode, - gen_rtx_LO_SUM (Pmode, reg, - gen_rtx_UNSPEC (SImode, - gen_rtvec (1, orig), - 0))); - } - else - pic_ref = gen_rtx_MEM (Pmode, - gen_rtx_PLUS (Pmode, - pic_offset_table_rtx, orig)); - current_function_uses_pic_offset_table = 1; - RTX_UNCHANGING_P (pic_ref) = 1; - emit_move_insn (reg, pic_ref); - return reg; - } - else if (GET_CODE (orig) == CONST) - { - rtx base; - - if (GET_CODE (XEXP (orig, 0)) == PLUS - && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx) - return orig; - - if (reg == 0) - abort (); - - if (GET_CODE (XEXP (orig, 0)) == PLUS) - { - base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg); - orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode, - base == reg ? 0 : reg); - } - else abort (); - if (GET_CODE (orig) == CONST_INT) - { - if (INT_14_BITS (orig)) - return plus_constant_for_output (base, INTVAL (orig)); - orig = force_reg (Pmode, orig); - } - pic_ref = gen_rtx_PLUS (Pmode, base, orig); - /* Likewise, should we set special REG_NOTEs here? */ - } - return pic_ref; -} - -/* 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. - - For the PA, transform: - - memory(X + <large int>) - - into: - - if (<large int> & mask) >= 16 - Y = (<large int> & ~mask) + mask + 1 Round up. - else - Y = (<large int> & ~mask) Round down. - Z = X + Y - memory (Z + (<large int> - Y)); - - This is for CSE to find several similar references, and only use one Z. - - X can either be a SYMBOL_REF or REG, but because combine can not - perform a 4->2 combination we do nothing for SYMBOL_REF + D where - D will not fit in 14 bits. - - MODE_FLOAT references allow displacements which fit in 5 bits, so use - 0x1f as the mask. - - MODE_INT references allow displacements which fit in 14 bits, so use - 0x3fff as the mask. - - This relies on the fact that most mode MODE_FLOAT references will use FP - registers and most mode MODE_INT references will use integer registers. - (In the rare case of an FP register used in an integer MODE, we depend - on secondary reloads to clean things up.) - - - It is also beneficial to handle (plus (mult (X) (Y)) (Z)) in a special - manner if Y is 2, 4, or 8. (allows more shadd insns and shifted indexed - addressing modes to be used). - - Put X and Z into registers. Then put the entire expression into - a register. */ - -rtx -hppa_legitimize_address (x, oldx, mode) - rtx x, oldx ATTRIBUTE_UNUSED; - enum machine_mode mode; -{ - rtx orig = x; - - if (flag_pic) - return legitimize_pic_address (x, mode, gen_reg_rtx (Pmode)); - - /* Strip off CONST. */ - if (GET_CODE (x) == CONST) - x = XEXP (x, 0); - - /* Special case. Get the SYMBOL_REF into a register and use indexing. - That should always be safe. */ - if (GET_CODE (x) == PLUS - && GET_CODE (XEXP (x, 0)) == REG - && GET_CODE (XEXP (x, 1)) == SYMBOL_REF) - { - rtx reg = force_reg (SImode, XEXP (x, 1)); - return force_reg (SImode, gen_rtx_PLUS (SImode, reg, XEXP (x, 0))); - } - - /* Note we must reject symbols which represent function addresses - since the assembler/linker can't handle arithmetic on plabels. */ - if (GET_CODE (x) == PLUS - && GET_CODE (XEXP (x, 1)) == CONST_INT - && ((GET_CODE (XEXP (x, 0)) == SYMBOL_REF - && !FUNCTION_NAME_P (XSTR (XEXP (x, 0), 0))) - || GET_CODE (XEXP (x, 0)) == REG)) - { - rtx int_part, ptr_reg; - int newoffset; - int offset = INTVAL (XEXP (x, 1)); - int mask = GET_MODE_CLASS (mode) == MODE_FLOAT ? 0x1f : 0x3fff; - - /* CYGNUS LOCAL pa8000/law */ - mask = (GET_MODE_CLASS (mode) == MODE_FLOAT - ? (TARGET_PARISC_2_0 ? 0x3fff : 0x1f) : 0x3fff); - /* END CYGNUS LOCAL */ - - /* Choose which way to round the offset. Round up if we - are >= halfway to the next boundary. */ - if ((offset & mask) >= ((mask + 1) / 2)) - newoffset = (offset & ~ mask) + mask + 1; - else - newoffset = (offset & ~ mask); - - /* If the newoffset will not fit in 14 bits (ldo), then - handling this would take 4 or 5 instructions (2 to load - the SYMBOL_REF + 1 or 2 to load the newoffset + 1 to - add the new offset and the SYMBOL_REF.) Combine can - not handle 4->2 or 5->2 combinations, so do not create - them. */ - if (! VAL_14_BITS_P (newoffset) - && GET_CODE (XEXP (x, 0)) == SYMBOL_REF) - { - rtx const_part - = gen_rtx_CONST (VOIDmode, gen_rtx_PLUS (Pmode, - XEXP (x, 0), - GEN_INT (newoffset))); - rtx tmp_reg - = force_reg (Pmode, - gen_rtx_HIGH (Pmode, const_part)); - ptr_reg - = force_reg (Pmode, - gen_rtx_LO_SUM (Pmode, tmp_reg, const_part)); - } - else - { - if (! VAL_14_BITS_P (newoffset)) - int_part = force_reg (Pmode, GEN_INT (newoffset)); - else - int_part = GEN_INT (newoffset); - - ptr_reg = force_reg (Pmode, - gen_rtx_PLUS (Pmode, - force_reg (Pmode, XEXP (x, 0)), - int_part)); - } - return plus_constant (ptr_reg, offset - newoffset); - } - - /* Handle (plus (mult (a) (shadd_constant)) (b)). */ - - if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT - && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT - && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))) - && (GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == 'o' - || GET_CODE (XEXP (x, 1)) == SUBREG) - && GET_CODE (XEXP (x, 1)) != CONST) - { - int val = INTVAL (XEXP (XEXP (x, 0), 1)); - rtx reg1, reg2; - - reg1 = XEXP (x, 1); - if (GET_CODE (reg1) != REG) - reg1 = force_reg (Pmode, force_operand (reg1, 0)); - - reg2 = XEXP (XEXP (x, 0), 0); - if (GET_CODE (reg2) != REG) - reg2 = force_reg (Pmode, force_operand (reg2, 0)); - - return force_reg (Pmode, gen_rtx_PLUS (Pmode, - gen_rtx_MULT (Pmode, reg2, - GEN_INT (val)), - reg1)); - } - - /* Similarly for (plus (plus (mult (a) (shadd_constant)) (b)) (c)). - - Only do so for floating point modes since this is more speculative - and we lose if it's an integer store. */ - if (GET_CODE (x) == PLUS - && GET_CODE (XEXP (x, 0)) == PLUS - && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT - && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT - && shadd_constant_p (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1))) - && (mode == SFmode || mode == DFmode)) - { - - /* First, try and figure out what to use as a base register. */ - rtx reg1, reg2, base, idx, orig_base; - - reg1 = XEXP (XEXP (x, 0), 1); - reg2 = XEXP (x, 1); - base = NULL_RTX; - idx = NULL_RTX; - - /* Make sure they're both regs. If one was a SYMBOL_REF [+ const], - then emit_move_sequence will turn on REGNO_POINTER_FLAG so we'll - know it's a base register below. */ - if (GET_CODE (reg1) != REG) - reg1 = force_reg (Pmode, force_operand (reg1, 0)); - - if (GET_CODE (reg2) != REG) - reg2 = force_reg (Pmode, force_operand (reg2, 0)); - - /* Figure out what the base and index are. */ - - if (GET_CODE (reg1) == REG - && REGNO_POINTER_FLAG (REGNO (reg1))) - { - base = reg1; - orig_base = XEXP (XEXP (x, 0), 1); - idx = gen_rtx_PLUS (Pmode, - gen_rtx_MULT (Pmode, - XEXP (XEXP (XEXP (x, 0), 0), 0), - XEXP (XEXP (XEXP (x, 0), 0), 1)), - XEXP (x, 1)); - } - else if (GET_CODE (reg2) == REG - && REGNO_POINTER_FLAG (REGNO (reg2))) - { - base = reg2; - orig_base = XEXP (x, 1); - idx = XEXP (x, 0); - } - - if (base == 0) - return orig; - - /* If the index adds a large constant, try to scale the - constant so that it can be loaded with only one insn. */ - if (GET_CODE (XEXP (idx, 1)) == CONST_INT - && VAL_14_BITS_P (INTVAL (XEXP (idx, 1)) - / INTVAL (XEXP (XEXP (idx, 0), 1))) - && INTVAL (XEXP (idx, 1)) % INTVAL (XEXP (XEXP (idx, 0), 1)) == 0) - { - /* Divide the CONST_INT by the scale factor, then add it to A. */ - int val = INTVAL (XEXP (idx, 1)); - - val /= INTVAL (XEXP (XEXP (idx, 0), 1)); - reg1 = XEXP (XEXP (idx, 0), 0); - if (GET_CODE (reg1) != REG) - reg1 = force_reg (Pmode, force_operand (reg1, 0)); - - reg1 = force_reg (Pmode, gen_rtx_PLUS (Pmode, reg1, GEN_INT (val))); - - /* We can now generate a simple scaled indexed address. */ - return force_reg (Pmode, - gen_rtx_PLUS (Pmode, - gen_rtx_MULT (Pmode, reg1, - XEXP (XEXP (idx, 0), 1)), - base)); - } - - /* If B + C is still a valid base register, then add them. */ - if (GET_CODE (XEXP (idx, 1)) == CONST_INT - && INTVAL (XEXP (idx, 1)) <= 4096 - && INTVAL (XEXP (idx, 1)) >= -4096) - { - int val = INTVAL (XEXP (XEXP (idx, 0), 1)); - rtx reg1, reg2; - - reg1 = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, XEXP (idx, 1))); - - reg2 = XEXP (XEXP (idx, 0), 0); - if (GET_CODE (reg2) != CONST_INT) - reg2 = force_reg (Pmode, force_operand (reg2, 0)); - - return force_reg (Pmode, gen_rtx_PLUS (Pmode, - gen_rtx_MULT (Pmode, reg2, - GEN_INT (val)), - reg1)); - } - - /* Get the index into a register, then add the base + index and - return a register holding the result. */ - - /* First get A into a register. */ - reg1 = XEXP (XEXP (idx, 0), 0); - if (GET_CODE (reg1) != REG) - reg1 = force_reg (Pmode, force_operand (reg1, 0)); - - /* And get B into a register. */ - reg2 = XEXP (idx, 1); - if (GET_CODE (reg2) != REG) - reg2 = force_reg (Pmode, force_operand (reg2, 0)); - - reg1 = force_reg (Pmode, - gen_rtx_PLUS (Pmode, - gen_rtx_MULT (Pmode, reg1, - XEXP (XEXP (idx, 0), 1)), - reg2)); - - /* Add the result to our base register and return. */ - return force_reg (Pmode, gen_rtx_PLUS (Pmode, base, reg1)); - - } - - /* Uh-oh. We might have an address for x[n-100000]. This needs - special handling to avoid creating an indexed memory address - with x-100000 as the base. - - If the constant part is small enough, then it's still safe because - there is a guard page at the beginning and end of the data segment. - - Scaled references are common enough that we want to try and rearrange the - terms so that we can use indexing for these addresses too. Only - do the optimization for floatint point modes. */ - - if (GET_CODE (x) == PLUS - && symbolic_expression_p (XEXP (x, 1))) - { - /* Ugly. We modify things here so that the address offset specified - by the index expression is computed first, then added to x to form - the entire address. */ - - rtx regx1, regx2, regy1, regy2, y; - - /* Strip off any CONST. */ - y = XEXP (x, 1); - if (GET_CODE (y) == CONST) - y = XEXP (y, 0); - - if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS) - { - /* See if this looks like - (plus (mult (reg) (shadd_const)) - (const (plus (symbol_ref) (const_int)))) - - Where const_int is small. In that case the const - expression is a valid pointer for indexing. - - If const_int is big, but can be divided evenly by shadd_const - and added to (reg). This allows more scaled indexed addresses. */ - if (GET_CODE (XEXP (y, 0)) == SYMBOL_REF - && GET_CODE (XEXP (x, 0)) == MULT - && GET_CODE (XEXP (y, 1)) == CONST_INT - && INTVAL (XEXP (y, 1)) >= -4096 - && INTVAL (XEXP (y, 1)) <= 4095 - && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT - && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))) - { - int val = INTVAL (XEXP (XEXP (x, 0), 1)); - rtx reg1, reg2; - - reg1 = XEXP (x, 1); - if (GET_CODE (reg1) != REG) - reg1 = force_reg (Pmode, force_operand (reg1, 0)); - - reg2 = XEXP (XEXP (x, 0), 0); - if (GET_CODE (reg2) != REG) - reg2 = force_reg (Pmode, force_operand (reg2, 0)); - - return force_reg (Pmode, - gen_rtx_PLUS (Pmode, - gen_rtx_MULT (Pmode, reg2, - GEN_INT (val)), - reg1)); - } - else if ((mode == DFmode || mode == SFmode) - && GET_CODE (XEXP (y, 0)) == SYMBOL_REF - && GET_CODE (XEXP (x, 0)) == MULT - && GET_CODE (XEXP (y, 1)) == CONST_INT - && INTVAL (XEXP (y, 1)) % INTVAL (XEXP (XEXP (x, 0), 1)) == 0 - && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT - && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))) - { - regx1 - = force_reg (Pmode, GEN_INT (INTVAL (XEXP (y, 1)) - / INTVAL (XEXP (XEXP (x, 0), 1)))); - regx2 = XEXP (XEXP (x, 0), 0); - if (GET_CODE (regx2) != REG) - regx2 = force_reg (Pmode, force_operand (regx2, 0)); - regx2 = force_reg (Pmode, gen_rtx_fmt_ee (GET_CODE (y), Pmode, - regx2, regx1)); - return force_reg (Pmode, - gen_rtx_PLUS (Pmode, - gen_rtx_MULT (Pmode, regx2, - XEXP (XEXP (x, 0), - 1)), - force_reg (Pmode, XEXP (y, 0)))); - } - else if (GET_CODE (XEXP (y, 1)) == CONST_INT - && INTVAL (XEXP (y, 1)) >= -4096 - && INTVAL (XEXP (y, 1)) <= 4095) - { - /* This is safe because of the guard page at the - beginning and end of the data space. Just - return the original address. */ - return orig; - } - else - { - /* Doesn't look like one we can optimize. */ - regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0)); - regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0)); - regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0)); - regx1 = force_reg (Pmode, - gen_rtx_fmt_ee (GET_CODE (y), Pmode, - regx1, regy2)); - return force_reg (Pmode, gen_rtx_PLUS (Pmode, regx1, regy1)); - } - } - } - - return orig; -} - -/* For the HPPA, REG and REG+CONST is cost 0 - and addresses involving symbolic constants are cost 2. - - PIC addresses are very expensive. - - It is no coincidence that this has the same structure - as GO_IF_LEGITIMATE_ADDRESS. */ -int -hppa_address_cost (X) - rtx X; -{ - if (GET_CODE (X) == PLUS) - return 1; - else if (GET_CODE (X) == LO_SUM) - return 1; - else if (GET_CODE (X) == HIGH) - return 2; - return 4; -} - -/* Emit insns to move operands[1] into operands[0]. - - Return 1 if we have written out everything that needs to be done to - do the move. Otherwise, return 0 and the caller will emit the move - normally. */ - -int -emit_move_sequence (operands, mode, scratch_reg) - rtx *operands; - enum machine_mode mode; - rtx scratch_reg; -{ - register rtx operand0 = operands[0]; - register rtx operand1 = operands[1]; - register rtx tem; - - if (scratch_reg - && reload_in_progress && GET_CODE (operand0) == REG - && REGNO (operand0) >= FIRST_PSEUDO_REGISTER) - operand0 = reg_equiv_mem[REGNO (operand0)]; - else if (scratch_reg - && reload_in_progress && GET_CODE (operand0) == SUBREG - && GET_CODE (SUBREG_REG (operand0)) == REG - && REGNO (SUBREG_REG (operand0)) >= FIRST_PSEUDO_REGISTER) - { - SUBREG_REG (operand0) = reg_equiv_mem[REGNO (SUBREG_REG (operand0))]; - operand0 = alter_subreg (operand0); - } - - if (scratch_reg - && reload_in_progress && GET_CODE (operand1) == REG - && REGNO (operand1) >= FIRST_PSEUDO_REGISTER) - operand1 = reg_equiv_mem[REGNO (operand1)]; - else if (scratch_reg - && reload_in_progress && GET_CODE (operand1) == SUBREG - && GET_CODE (SUBREG_REG (operand1)) == REG - && REGNO (SUBREG_REG (operand1)) >= FIRST_PSEUDO_REGISTER) - { - SUBREG_REG (operand1) = reg_equiv_mem[REGNO (SUBREG_REG (operand1))]; - operand1 = alter_subreg (operand1); - } - - if (scratch_reg && reload_in_progress && GET_CODE (operand0) == MEM - && ((tem = find_replacement (&XEXP (operand0, 0))) - != XEXP (operand0, 0))) - operand0 = gen_rtx_MEM (GET_MODE (operand0), tem); - if (scratch_reg && reload_in_progress && GET_CODE (operand1) == MEM - && ((tem = find_replacement (&XEXP (operand1, 0))) - != XEXP (operand1, 0))) - operand1 = gen_rtx_MEM (GET_MODE (operand1), tem); - - /* Handle secondary reloads for loads/stores of FP registers from - REG+D addresses where D does not fit in 5 bits, including - (subreg (mem (addr))) cases. */ - if (fp_reg_operand (operand0, mode) - && ((GET_CODE (operand1) == MEM - && ! memory_address_p (DFmode, XEXP (operand1, 0))) - || ((GET_CODE (operand1) == SUBREG - && GET_CODE (XEXP (operand1, 0)) == MEM - && !memory_address_p (DFmode, XEXP (XEXP (operand1, 0), 0))))) - && scratch_reg) - { - if (GET_CODE (operand1) == SUBREG) - operand1 = XEXP (operand1, 0); - - scratch_reg = gen_rtx_REG (SImode, REGNO (scratch_reg)); - - /* D might not fit in 14 bits either; for such cases load D into - scratch reg. */ - if (!memory_address_p (SImode, XEXP (operand1, 0))) - { - emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1)); - emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand1, 0)), - SImode, - XEXP (XEXP (operand1, 0), 0), - scratch_reg)); - } - else - emit_move_insn (scratch_reg, XEXP (operand1, 0)); - emit_insn (gen_rtx_SET (VOIDmode, operand0, gen_rtx_MEM (mode, - scratch_reg))); - return 1; - } - else if (fp_reg_operand (operand1, mode) - && ((GET_CODE (operand0) == MEM - && ! memory_address_p (DFmode, XEXP (operand0, 0))) - || ((GET_CODE (operand0) == SUBREG) - && GET_CODE (XEXP (operand0, 0)) == MEM - && !memory_address_p (DFmode, XEXP (XEXP (operand0, 0), 0)))) - && scratch_reg) - { - if (GET_CODE (operand0) == SUBREG) - operand0 = XEXP (operand0, 0); - - scratch_reg = gen_rtx_REG (SImode, REGNO (scratch_reg)); - /* D might not fit in 14 bits either; for such cases load D into - scratch reg. */ - if (!memory_address_p (SImode, XEXP (operand0, 0))) - { - emit_move_insn (scratch_reg, XEXP (XEXP (operand0, 0), 1)); - emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand0, - 0)), - SImode, - XEXP (XEXP (operand0, 0), - 0), - scratch_reg)); - } - else - emit_move_insn (scratch_reg, XEXP (operand0, 0)); - emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (mode, scratch_reg), - operand1)); - return 1; - } - /* Handle secondary reloads for loads of FP registers from constant - expressions by forcing the constant into memory. - - use scratch_reg to hold the address of the memory location. - - ??? The proper fix is to change PREFERRED_RELOAD_CLASS to return - NO_REGS when presented with a const_int and an register class - containing only FP registers. Doing so unfortunately creates - more problems than it solves. Fix this for 2.5. */ - else if (fp_reg_operand (operand0, mode) - && CONSTANT_P (operand1) - && scratch_reg) - { - rtx xoperands[2]; - - /* Force the constant into memory and put the address of the - memory location into scratch_reg. */ - xoperands[0] = scratch_reg; - xoperands[1] = XEXP (force_const_mem (mode, operand1), 0); - emit_move_sequence (xoperands, Pmode, 0); - - /* Now load the destination register. */ - emit_insn (gen_rtx_SET (mode, operand0, gen_rtx_MEM (mode, scratch_reg))); - return 1; - } - /* Handle secondary reloads for SAR. These occur when trying to load - the SAR from memory a FP register, or with a constant. */ - else if (GET_CODE (operand0) == REG - && REGNO_REG_CLASS (REGNO (operand0)) == SHIFT_REGS - && (GET_CODE (operand1) == MEM - || GET_CODE (operand1) == CONST_INT - || (GET_CODE (operand1) == REG - && FP_REG_CLASS_P (REGNO_REG_CLASS (REGNO (operand1))))) - && scratch_reg) - { - /* D might not fit in 14 bits either; for such cases load D into - scratch reg. */ - if (GET_CODE (operand1) == MEM - && !memory_address_p (SImode, XEXP (operand1, 0))) - { - emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1)); - emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand1, - 0)), - SImode, - XEXP (XEXP (operand1, 0), - 0), - scratch_reg)); - emit_move_insn (scratch_reg, gen_rtx_MEM (GET_MODE (operand1), - scratch_reg)); - } - else - emit_move_insn (scratch_reg, operand1); - emit_move_insn (operand0, scratch_reg); - return 1; - } - /* Handle most common case: storing into a register. */ - else if (register_operand (operand0, mode)) - { - if (register_operand (operand1, mode) - || (GET_CODE (operand1) == CONST_INT && INT_14_BITS (operand1)) - || (operand1 == CONST0_RTX (mode)) - || (GET_CODE (operand1) == HIGH - && !symbolic_operand (XEXP (operand1, 0), VOIDmode)) - /* Only `general_operands' can come here, so MEM is ok. */ - || GET_CODE (operand1) == MEM) - { - /* Run this case quickly. */ - emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1)); - return 1; - } - } - else if (GET_CODE (operand0) == MEM) - { - if (mode == DFmode && operand1 == CONST0_RTX (mode) - && !(reload_in_progress || reload_completed)) - { - rtx temp = gen_reg_rtx (DFmode); - - emit_insn (gen_rtx_SET (VOIDmode, temp, operand1)); - emit_insn (gen_rtx_SET (VOIDmode, operand0, temp)); - return 1; - } - if (register_operand (operand1, mode) || operand1 == CONST0_RTX (mode)) - { - /* Run this case quickly. */ - emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1)); - return 1; - } - if (! (reload_in_progress || reload_completed)) - { - operands[0] = validize_mem (operand0); - operands[1] = operand1 = force_reg (mode, operand1); - } - } - - /* Simplify the source if we need to. - Note we do have to handle function labels here, even though we do - not consider them legitimate constants. Loop optimizations can - call the emit_move_xxx with one as a source. */ - if ((GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode)) - || function_label_operand (operand1, mode) - || (GET_CODE (operand1) == HIGH - && symbolic_operand (XEXP (operand1, 0), mode))) - { - int ishighonly = 0; - - if (GET_CODE (operand1) == HIGH) - { - ishighonly = 1; - operand1 = XEXP (operand1, 0); - } - if (symbolic_operand (operand1, mode)) - { - /* Argh. The assembler and linker can't handle arithmetic - involving plabels. - - So we force the plabel into memory, load operand0 from - the memory location, then add in the constant part. */ - if ((GET_CODE (operand1) == CONST - && GET_CODE (XEXP (operand1, 0)) == PLUS - && function_label_operand (XEXP (XEXP (operand1, 0), 0), Pmode)) - || function_label_operand (operand1, mode)) - { - rtx temp, const_part; - - /* Figure out what (if any) scratch register to use. */ - if (reload_in_progress || reload_completed) - scratch_reg = scratch_reg ? scratch_reg : operand0; - else if (flag_pic) - scratch_reg = gen_reg_rtx (Pmode); - - if (GET_CODE (operand1) == CONST) - { - /* Save away the constant part of the expression. */ - const_part = XEXP (XEXP (operand1, 0), 1); - if (GET_CODE (const_part) != CONST_INT) - abort (); - - /* Force the function label into memory. */ - temp = force_const_mem (mode, XEXP (XEXP (operand1, 0), 0)); - } - else - { - /* No constant part. */ - const_part = NULL_RTX; - - /* Force the function label into memory. */ - temp = force_const_mem (mode, operand1); - } - - - /* Get the address of the memory location. PIC-ify it if - necessary. */ - temp = XEXP (temp, 0); - if (flag_pic) - temp = legitimize_pic_address (temp, mode, scratch_reg); - - /* Put the address of the memory location into our destination - register. */ - operands[1] = temp; - emit_move_sequence (operands, mode, scratch_reg); - - /* Now load from the memory location into our destination - register. */ - operands[1] = gen_rtx_MEM (Pmode, operands[0]); - emit_move_sequence (operands, mode, scratch_reg); - - /* And add back in the constant part. */ - if (const_part != NULL_RTX) - expand_inc (operand0, const_part); - - return 1; - } - - if (flag_pic) - { - rtx temp; - - if (reload_in_progress || reload_completed) - temp = scratch_reg ? scratch_reg : operand0; - else - temp = gen_reg_rtx (Pmode); - - /* (const (plus (symbol) (const_int))) must be forced to - memory during/after reload if the const_int will not fit - in 14 bits. */ - if (GET_CODE (operand1) == CONST - && GET_CODE (XEXP (operand1, 0)) == PLUS - && GET_CODE (XEXP (XEXP (operand1, 0), 1)) == CONST_INT - && !INT_14_BITS (XEXP (XEXP (operand1, 0), 1)) - && (reload_completed || reload_in_progress) - && flag_pic) - { - operands[1] = force_const_mem (mode, operand1); - operands[1] = legitimize_pic_address (XEXP (operands[1], 0), - mode, temp); - emit_move_sequence (operands, mode, temp); - } - else - { - operands[1] = legitimize_pic_address (operand1, mode, temp); - emit_insn (gen_rtx_SET (VOIDmode, operand0, operands[1])); - } - } - /* On the HPPA, references to data space are supposed to use dp, - register 27, but showing it in the RTL inhibits various cse - and loop optimizations. */ - else - { - rtx temp, set; - - if (reload_in_progress || reload_completed) - temp = scratch_reg ? scratch_reg : operand0; - else - temp = gen_reg_rtx (mode); - - /* Loading a SYMBOL_REF into a register makes that register - safe to be used as the base in an indexed address. - - Don't mark hard registers though. That loses. */ - if (GET_CODE (operand0) == REG - && REGNO (operand0) >= FIRST_PSEUDO_REGISTER) - REGNO_POINTER_FLAG (REGNO (operand0)) = 1; - if (REGNO (temp) >= FIRST_PSEUDO_REGISTER) - REGNO_POINTER_FLAG (REGNO (temp)) = 1; - if (ishighonly) - set = gen_rtx_SET (mode, operand0, temp); - else - set = gen_rtx_SET (VOIDmode, operand0, - gen_rtx_LO_SUM (mode, temp, operand1)); - - emit_insn (gen_rtx_SET (VOIDmode, - temp, - gen_rtx_HIGH (mode, operand1))); - emit_insn (set); - - } - return 1; - } - else if (GET_CODE (operand1) != CONST_INT - || ! cint_ok_for_move (INTVAL (operand1))) - { - rtx temp; - - if (reload_in_progress || reload_completed) - temp = operand0; - else - temp = gen_reg_rtx (mode); - - emit_insn (gen_rtx_SET (VOIDmode, temp, - gen_rtx_HIGH (mode, operand1))); - operands[1] = gen_rtx_LO_SUM (mode, temp, operand1); - } - } - /* Now have insn-emit do whatever it normally does. */ - return 0; -} - -/* Examine EXP and return nonzero if it contains an ADDR_EXPR (meaning - it will need a link/runtime reloc). */ - -int -reloc_needed (exp) - tree exp; -{ - int reloc = 0; - - switch (TREE_CODE (exp)) - { - case ADDR_EXPR: - return 1; - - case PLUS_EXPR: - case MINUS_EXPR: - reloc = reloc_needed (TREE_OPERAND (exp, 0)); - reloc |= reloc_needed (TREE_OPERAND (exp, 1)); - break; - - case NOP_EXPR: - case CONVERT_EXPR: - case NON_LVALUE_EXPR: - reloc = reloc_needed (TREE_OPERAND (exp, 0)); - break; - - case CONSTRUCTOR: - { - register tree link; - for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) - if (TREE_VALUE (link) != 0) - reloc |= reloc_needed (TREE_VALUE (link)); - } - break; - - case ERROR_MARK: - break; - - default: - break; - } - return reloc; -} - -/* Does operand (which is a symbolic_operand) live in text space? If - so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. */ - -int -read_only_operand (operand) - rtx operand; -{ - if (GET_CODE (operand) == CONST) - operand = XEXP (XEXP (operand, 0), 0); - if (flag_pic) - { - if (GET_CODE (operand) == SYMBOL_REF) - return SYMBOL_REF_FLAG (operand) && !CONSTANT_POOL_ADDRESS_P (operand); - } - else - { - if (GET_CODE (operand) == SYMBOL_REF) - return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand); - } - return 1; -} - - -/* Return the best assembler insn template - for moving operands[1] into operands[0] as a fullword. */ -char * -singlemove_string (operands) - rtx *operands; -{ - HOST_WIDE_INT intval; - - if (GET_CODE (operands[0]) == MEM) - return "stw %r1,%0"; - if (GET_CODE (operands[1]) == MEM) - return "ldw %1,%0"; - if (GET_CODE (operands[1]) == CONST_DOUBLE) - { - long i; - REAL_VALUE_TYPE d; - - if (GET_MODE (operands[1]) != SFmode) - abort (); - - /* Translate the CONST_DOUBLE to a CONST_INT with the same target - bit pattern. */ - REAL_VALUE_FROM_CONST_DOUBLE (d, operands[1]); - REAL_VALUE_TO_TARGET_SINGLE (d, i); - - operands[1] = GEN_INT (i); - /* Fall through to CONST_INT case. */ - } - if (GET_CODE (operands[1]) == CONST_INT) - { - intval = INTVAL (operands[1]); - - if (VAL_14_BITS_P (intval)) - return "ldi %1,%0"; - else if ((intval & 0x7ff) == 0) - return "ldil L'%1,%0"; - else if (zdepi_cint_p (intval)) - return "zdepi %Z1,%0"; - else - return "ldil L'%1,%0\n\tldo R'%1(%0),%0"; - } - return "copy %1,%0"; -} - - -/* Compute position (in OP[1]) and width (in OP[2]) - useful for copying IMM to a register using the zdepi - instructions. Store the immediate value to insert in OP[0]. */ -void -compute_zdepi_operands (imm, op) - unsigned HOST_WIDE_INT imm; - unsigned *op; -{ - int lsb, len; - - /* Find the least significant set bit in IMM. */ - for (lsb = 0; lsb < 32; lsb++) - { - if ((imm & 1) != 0) - break; - imm >>= 1; - } - - /* Choose variants based on *sign* of the 5-bit field. */ - if ((imm & 0x10) == 0) - len = (lsb <= 28) ? 4 : 32 - lsb; - else - { - /* Find the width of the bitstring in IMM. */ - for (len = 5; len < 32; len++) - { - if ((imm & (1 << len)) == 0) - break; - } - - /* Sign extend IMM as a 5-bit value. */ - imm = (imm & 0xf) - 0x10; - } - - op[0] = imm; - op[1] = 31 - lsb; - op[2] = len; -} - -/* Output assembler code to perform a doubleword move insn - with operands OPERANDS. */ - -char * -output_move_double (operands) - rtx *operands; -{ - enum { REGOP, OFFSOP, MEMOP, CNSTOP, RNDOP } optype0, optype1; - rtx latehalf[2]; - rtx addreg0 = 0, addreg1 = 0; - - /* First classify both operands. */ - - if (REG_P (operands[0])) - optype0 = REGOP; - else if (offsettable_memref_p (operands[0])) - optype0 = OFFSOP; - else if (GET_CODE (operands[0]) == MEM) - optype0 = MEMOP; - else - optype0 = RNDOP; - - if (REG_P (operands[1])) - optype1 = REGOP; - else if (CONSTANT_P (operands[1])) - optype1 = CNSTOP; - else if (offsettable_memref_p (operands[1])) - optype1 = OFFSOP; - else if (GET_CODE (operands[1]) == MEM) - optype1 = MEMOP; - else - optype1 = RNDOP; - - /* Check for the cases that the operand constraints are not - supposed to allow to happen. Abort if we get one, - because generating code for these cases is painful. */ - - if (optype0 != REGOP && optype1 != REGOP) - abort (); - - /* Handle auto decrementing and incrementing loads and stores - specifically, since the structure of the function doesn't work - for them without major modification. Do it better when we learn - this port about the general inc/dec addressing of PA. - (This was written by tege. Chide him if it doesn't work.) */ - - if (optype0 == MEMOP) - { - /* We have to output the address syntax ourselves, since print_operand - doesn't deal with the addresses we want to use. Fix this later. */ - - rtx addr = XEXP (operands[0], 0); - if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC) - { - rtx high_reg = gen_rtx_SUBREG (SImode, operands[1], 0); - - operands[0] = XEXP (addr, 0); - if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG) - abort (); - - if (!reg_overlap_mentioned_p (high_reg, addr)) - { - /* No overlap between high target register and address - register. (We do this in a non-obvious way to - save a register file writeback) */ - if (GET_CODE (addr) == POST_INC) - return "stws,ma %1,8(0,%0)\n\tstw %R1,-4(0,%0)"; - return "stws,ma %1,-8(0,%0)\n\tstw %R1,12(0,%0)"; - } - else - abort(); - } - else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC) - { - rtx high_reg = gen_rtx_SUBREG (SImode, operands[1], 0); - - operands[0] = XEXP (addr, 0); - if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG) - abort (); - - if (!reg_overlap_mentioned_p (high_reg, addr)) - { - /* No overlap between high target register and address - register. (We do this in a non-obvious way to - save a register file writeback) */ - if (GET_CODE (addr) == PRE_INC) - return "stws,mb %1,8(0,%0)\n\tstw %R1,4(0,%0)"; - return "stws,mb %1,-8(0,%0)\n\tstw %R1,4(0,%0)"; - } - else - abort(); - } - } - if (optype1 == MEMOP) - { - /* We have to output the address syntax ourselves, since print_operand - doesn't deal with the addresses we want to use. Fix this later. */ - - rtx addr = XEXP (operands[1], 0); - if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC) - { - rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0); - - operands[1] = XEXP (addr, 0); - if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG) - abort (); - - if (!reg_overlap_mentioned_p (high_reg, addr)) - { - /* No overlap between high target register and address - register. (We do this in a non-obvious way to - save a register file writeback) */ - if (GET_CODE (addr) == POST_INC) - return "ldws,ma 8(0,%1),%0\n\tldw -4(0,%1),%R0"; - return "ldws,ma -8(0,%1),%0\n\tldw 12(0,%1),%R0"; - } - else - { - /* This is an undefined situation. We should load into the - address register *and* update that register. Probably - we don't need to handle this at all. */ - if (GET_CODE (addr) == POST_INC) - return "ldw 4(0,%1),%R0\n\tldws,ma 8(0,%1),%0"; - return "ldw 4(0,%1),%R0\n\tldws,ma -8(0,%1),%0"; - } - } - else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC) - { - rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0); - - operands[1] = XEXP (addr, 0); - if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG) - abort (); - - if (!reg_overlap_mentioned_p (high_reg, addr)) - { - /* No overlap between high target register and address - register. (We do this in a non-obvious way to - save a register file writeback) */ - if (GET_CODE (addr) == PRE_INC) - return "ldws,mb 8(0,%1),%0\n\tldw 4(0,%1),%R0"; - return "ldws,mb -8(0,%1),%0\n\tldw 4(0,%1),%R0"; - } - else - { - /* This is an undefined situation. We should load into the - address register *and* update that register. Probably - we don't need to handle this at all. */ - if (GET_CODE (addr) == PRE_INC) - return "ldw 12(0,%1),%R0\n\tldws,mb 8(0,%1),%0"; - return "ldw -4(0,%1),%R0\n\tldws,mb -8(0,%1),%0"; - } - } - else if (GET_CODE (addr) == PLUS - && GET_CODE (XEXP (addr, 0)) == MULT) - { - rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0); - - if (!reg_overlap_mentioned_p (high_reg, addr)) - { - rtx xoperands[3]; - - xoperands[0] = high_reg; - xoperands[1] = XEXP (addr, 1); - xoperands[2] = XEXP (XEXP (addr, 0), 0); - xoperands[3] = XEXP (XEXP (addr, 0), 1); - output_asm_insn ("sh%O3addl %2,%1,%0", xoperands); - return "ldw 4(0,%0),%R0\n\tldw 0(0,%0),%0"; - } - else - { - rtx xoperands[3]; - - xoperands[0] = high_reg; - xoperands[1] = XEXP (addr, 1); - xoperands[2] = XEXP (XEXP (addr, 0), 0); - xoperands[3] = XEXP (XEXP (addr, 0), 1); - output_asm_insn ("sh%O3addl %2,%1,%R0", xoperands); - return "ldw 0(0,%R0),%0\n\tldw 4(0,%R0),%R0"; - } - - } - } - - /* If an operand is an unoffsettable memory ref, find a register - we can increment temporarily to make it refer to the second word. */ - - if (optype0 == MEMOP) - addreg0 = find_addr_reg (XEXP (operands[0], 0)); - - if (optype1 == MEMOP) - addreg1 = find_addr_reg (XEXP (operands[1], 0)); - - /* Ok, we can do one word at a time. - Normally we do the low-numbered word first. - - In either case, set up in LATEHALF the operands to use - for the high-numbered word and in some cases alter the - operands in OPERANDS to be suitable for the low-numbered word. */ - - if (optype0 == REGOP) - latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); - else if (optype0 == OFFSOP) - latehalf[0] = adj_offsettable_operand (operands[0], 4); - else - latehalf[0] = operands[0]; - - if (optype1 == REGOP) - latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1); - else if (optype1 == OFFSOP) - latehalf[1] = adj_offsettable_operand (operands[1], 4); - else if (optype1 == CNSTOP) - split_double (operands[1], &operands[1], &latehalf[1]); - else - latehalf[1] = operands[1]; - - /* If the first move would clobber the source of the second one, - do them in the other order. - - This can happen in two cases: - - mem -> register where the first half of the destination register - is the same register used in the memory's address. Reload - can create such insns. - - mem in this case will be either register indirect or register - indirect plus a valid offset. - - register -> register move where REGNO(dst) == REGNO(src + 1) - someone (Tim/Tege?) claimed this can happen for parameter loads. - - Handle mem -> register case first. */ - if (optype0 == REGOP - && (optype1 == MEMOP || optype1 == OFFSOP) - && refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - { - /* Do the late half first. */ - if (addreg1) - output_asm_insn ("ldo 4(%0),%0", &addreg1); - output_asm_insn (singlemove_string (latehalf), latehalf); - - /* Then clobber. */ - if (addreg1) - output_asm_insn ("ldo -4(%0),%0", &addreg1); - return singlemove_string (operands); - } - - /* Now handle register -> register case. */ - if (optype0 == REGOP && optype1 == REGOP - && REGNO (operands[0]) == REGNO (operands[1]) + 1) - { - output_asm_insn (singlemove_string (latehalf), latehalf); - return singlemove_string (operands); - } - - /* Normal case: do the two words, low-numbered first. */ - - output_asm_insn (singlemove_string (operands), operands); - - /* Make any unoffsettable addresses point at high-numbered word. */ - if (addreg0) - output_asm_insn ("ldo 4(%0),%0", &addreg0); - if (addreg1) - output_asm_insn ("ldo 4(%0),%0", &addreg1); - - /* Do that word. */ - output_asm_insn (singlemove_string (latehalf), latehalf); - - /* Undo the adds we just did. */ - if (addreg0) - output_asm_insn ("ldo -4(%0),%0", &addreg0); - if (addreg1) - output_asm_insn ("ldo -4(%0),%0", &addreg1); - - return ""; -} - -char * -output_fp_move_double (operands) - rtx *operands; -{ - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1]) - || operands[1] == CONST0_RTX (GET_MODE (operands[0]))) - output_asm_insn ("fcpy,dbl %r1,%0", operands); - else - output_asm_insn ("fldd%F1 %1,%0", operands); - } - else if (FP_REG_P (operands[1])) - { - output_asm_insn ("fstd%F0 %1,%0", operands); - } - else if (operands[1] == CONST0_RTX (GET_MODE (operands[0]))) - { - if (GET_CODE (operands[0]) == REG) - { - rtx xoperands[2]; - xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); - xoperands[0] = operands[0]; - output_asm_insn ("copy %%r0,%0\n\tcopy %%r0,%1", xoperands); - } - /* This is a pain. You have to be prepared to deal with an - arbitrary address here including pre/post increment/decrement. - - so avoid this in the MD. */ - else - abort (); - } - else abort (); - return ""; -} - -/* Return a REG that occurs in ADDR with coefficient 1. - ADDR can be effectively incremented by incrementing REG. */ - -static rtx -find_addr_reg (addr) - rtx addr; -{ - while (GET_CODE (addr) == PLUS) - { - if (GET_CODE (XEXP (addr, 0)) == REG) - addr = XEXP (addr, 0); - else if (GET_CODE (XEXP (addr, 1)) == REG) - addr = XEXP (addr, 1); - else if (CONSTANT_P (XEXP (addr, 0))) - addr = XEXP (addr, 1); - else if (CONSTANT_P (XEXP (addr, 1))) - addr = XEXP (addr, 0); - else - abort (); - } - if (GET_CODE (addr) == REG) - return addr; - abort (); -} - -/* Emit code to perform a block move. - - OPERANDS[0] is the destination pointer as a REG, clobbered. - OPERANDS[1] is the source pointer as a REG, clobbered. - OPERANDS[2] is a register for temporary storage. - OPERANDS[4] is the size as a CONST_INT - OPERANDS[3] is a register for temporary storage. - OPERANDS[5] is the alignment safe to use, as a CONST_INT. - OPERANDS[6] is another temporary register. */ - -char * -output_block_move (operands, size_is_constant) - rtx *operands; - int size_is_constant ATTRIBUTE_UNUSED; -{ - int align = INTVAL (operands[5]); - unsigned long n_bytes = INTVAL (operands[4]); - - /* We can't move more than four bytes at a time because the PA - has no longer integer move insns. (Could use fp mem ops?) */ - if (align > 4) - align = 4; - - /* Note that we know each loop below will execute at least twice - (else we would have open-coded the copy). */ - switch (align) - { - case 4: - /* Pre-adjust the loop counter. */ - operands[4] = GEN_INT (n_bytes - 8); - output_asm_insn ("ldi %4,%2", operands); - - /* Copying loop. */ - output_asm_insn ("ldws,ma 4(0,%1),%3", operands); - output_asm_insn ("ldws,ma 4(0,%1),%6", operands); - output_asm_insn ("stws,ma %3,4(0,%0)", operands); - output_asm_insn ("addib,>= -8,%2,.-12", operands); - output_asm_insn ("stws,ma %6,4(0,%0)", operands); - - /* Handle the residual. There could be up to 7 bytes of - residual to copy! */ - if (n_bytes % 8 != 0) - { - operands[4] = GEN_INT (n_bytes % 4); - if (n_bytes % 8 >= 4) - output_asm_insn ("ldws,ma 4(0,%1),%3", operands); - if (n_bytes % 4 != 0) - output_asm_insn ("ldw 0(0,%1),%6", operands); - if (n_bytes % 8 >= 4) - output_asm_insn ("stws,ma %3,4(0,%0)", operands); - if (n_bytes % 4 != 0) - output_asm_insn ("stbys,e %6,%4(0,%0)", operands); - } - return ""; - - case 2: - /* Pre-adjust the loop counter. */ - operands[4] = GEN_INT (n_bytes - 4); - output_asm_insn ("ldi %4,%2", operands); - - /* Copying loop. */ - output_asm_insn ("ldhs,ma 2(0,%1),%3", operands); - output_asm_insn ("ldhs,ma 2(0,%1),%6", operands); - output_asm_insn ("sths,ma %3,2(0,%0)", operands); - output_asm_insn ("addib,>= -4,%2,.-12", operands); - output_asm_insn ("sths,ma %6,2(0,%0)", operands); - - /* Handle the residual. */ - if (n_bytes % 4 != 0) - { - if (n_bytes % 4 >= 2) - output_asm_insn ("ldhs,ma 2(0,%1),%3", operands); - if (n_bytes % 2 != 0) - output_asm_insn ("ldb 0(0,%1),%6", operands); - if (n_bytes % 4 >= 2) - output_asm_insn ("sths,ma %3,2(0,%0)", operands); - if (n_bytes % 2 != 0) - output_asm_insn ("stb %6,0(0,%0)", operands); - } - return ""; - - case 1: - /* Pre-adjust the loop counter. */ - operands[4] = GEN_INT (n_bytes - 2); - output_asm_insn ("ldi %4,%2", operands); - - /* Copying loop. */ - output_asm_insn ("ldbs,ma 1(0,%1),%3", operands); - output_asm_insn ("ldbs,ma 1(0,%1),%6", operands); - output_asm_insn ("stbs,ma %3,1(0,%0)", operands); - output_asm_insn ("addib,>= -2,%2,.-12", operands); - output_asm_insn ("stbs,ma %6,1(0,%0)", operands); - - /* Handle the residual. */ - if (n_bytes % 2 != 0) - { - output_asm_insn ("ldb 0(0,%1),%3", operands); - output_asm_insn ("stb %3,0(0,%0)", operands); - } - return ""; - - default: - abort (); - } -} - -/* Count the number of insns necessary to handle this block move. - - Basic structure is the same as emit_block_move, except that we - count insns rather than emit them. */ - -int -compute_movstrsi_length (insn) - rtx insn; -{ - rtx pat = PATTERN (insn); - int align = INTVAL (XEXP (XVECEXP (pat, 0, 6), 0)); - unsigned long n_bytes = INTVAL (XEXP (XVECEXP (pat, 0, 5), 0)); - unsigned int n_insns = 0; - - /* We can't move more than four bytes at a time because the PA - has no longer integer move insns. (Could use fp mem ops?) */ - if (align > 4) - align = 4; - - /* The basic copying loop. */ - n_insns = 6; - - /* Residuals. */ - if (n_bytes % (2 * align) != 0) - { - if ((n_bytes % (2 * align)) >= align) - n_insns += 2; - - if ((n_bytes % align) != 0) - n_insns += 2; - } - - /* Lengths are expressed in bytes now; each insn is 4 bytes. */ - return n_insns * 4; -} - - -char * -output_and (operands) - rtx *operands; -{ - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0) - { - unsigned HOST_WIDE_INT mask = INTVAL (operands[2]); - int ls0, ls1, ms0, p, len; - - for (ls0 = 0; ls0 < 32; ls0++) - if ((mask & (1 << ls0)) == 0) - break; - - for (ls1 = ls0; ls1 < 32; ls1++) - if ((mask & (1 << ls1)) != 0) - break; - - for (ms0 = ls1; ms0 < 32; ms0++) - if ((mask & (1 << ms0)) == 0) - break; - - if (ms0 != 32) - abort(); - - if (ls1 == 32) - { - len = ls0; - - if (len == 0) - abort (); - - operands[2] = GEN_INT (len); - return "extru %1,31,%2,%0"; - } - else - { - /* We could use this `depi' for the case above as well, but `depi' - requires one more register file access than an `extru'. */ - - p = 31 - ls0; - len = ls1 - ls0; - - operands[2] = GEN_INT (p); - operands[3] = GEN_INT (len); - return "depi 0,%2,%3,%0"; - } - } - else - return "and %1,%2,%0"; -} - -char * -output_ior (operands) - rtx *operands; -{ - unsigned HOST_WIDE_INT mask = INTVAL (operands[2]); - int bs0, bs1, p, len; - - if (INTVAL (operands[2]) == 0) - return "copy %1,%0"; - - for (bs0 = 0; bs0 < 32; bs0++) - if ((mask & (1 << bs0)) != 0) - break; - - for (bs1 = bs0; bs1 < 32; bs1++) - if ((mask & (1 << bs1)) == 0) - break; - - if (bs1 != 32 && ((unsigned HOST_WIDE_INT) 1 << bs1) <= mask) - abort(); - - p = 31 - bs0; - len = bs1 - bs0; - - operands[2] = GEN_INT (p); - operands[3] = GEN_INT (len); - return "depi -1,%2,%3,%0"; -} - -/* Output an ascii string. */ -void -output_ascii (file, p, size) - FILE *file; - unsigned char *p; - int size; -{ - int i; - int chars_output; - unsigned char partial_output[16]; /* Max space 4 chars can occupy. */ - - /* The HP assembler can only take strings of 256 characters at one - time. This is a limitation on input line length, *not* the - length of the string. Sigh. Even worse, it seems that the - restriction is in number of input characters (see \xnn & - \whatever). So we have to do this very carefully. */ - - fputs ("\t.STRING \"", file); - - chars_output = 0; - for (i = 0; i < size; i += 4) - { - int co = 0; - int io = 0; - for (io = 0, co = 0; io < MIN (4, size - i); io++) - { - register unsigned int c = p[i + io]; - - if (c == '\"' || c == '\\') - partial_output[co++] = '\\'; - if (c >= ' ' && c < 0177) - partial_output[co++] = c; - else - { - unsigned int hexd; - partial_output[co++] = '\\'; - partial_output[co++] = 'x'; - hexd = c / 16 - 0 + '0'; - if (hexd > '9') - hexd -= '9' - 'a' + 1; - partial_output[co++] = hexd; - hexd = c % 16 - 0 + '0'; - if (hexd > '9') - hexd -= '9' - 'a' + 1; - partial_output[co++] = hexd; - } - } - if (chars_output + co > 243) - { - fputs ("\"\n\t.STRING \"", file); - chars_output = 0; - } - fwrite (partial_output, 1, co, file); - chars_output += co; - co = 0; - } - fputs ("\"\n", file); -} - -/* Try to rewrite floating point comparisons & branches to avoid - useless add,tr insns. - - CHECK_NOTES is nonzero if we should examine REG_DEAD notes - to see if FPCC is dead. CHECK_NOTES is nonzero for the - first attempt to remove useless add,tr insns. It is zero - for the second pass as reorg sometimes leaves bogus REG_DEAD - notes lying around. - - When CHECK_NOTES is zero we can only eliminate add,tr insns - when there's a 1:1 correspondence between fcmp and ftest/fbranch - instructions. */ -void -remove_useless_addtr_insns (insns, check_notes) - rtx insns; - int check_notes; -{ - rtx insn; - static int pass = 0; - - /* This is fairly cheap, so always run it when optimizing. */ - if (optimize > 0) - { - int fcmp_count = 0; - int fbranch_count = 0; - - /* Walk all the insns in this function looking for fcmp & fbranch - instructions. Keep track of how many of each we find. */ - insns = get_insns (); - for (insn = insns; insn; insn = next_insn (insn)) - { - rtx tmp; - - /* Ignore anything that isn't an INSN or a JUMP_INSN. */ - if (GET_CODE (insn) != INSN && GET_CODE (insn) != JUMP_INSN) - continue; - - tmp = PATTERN (insn); - - /* It must be a set. */ - if (GET_CODE (tmp) != SET) - continue; - - /* If the destination is CCFP, then we've found an fcmp insn. */ - tmp = SET_DEST (tmp); - if (GET_CODE (tmp) == REG && REGNO (tmp) == 0) - { - fcmp_count++; - continue; - } - - tmp = PATTERN (insn); - /* If this is an fbranch instruction, bump the fbranch counter. */ - if (GET_CODE (tmp) == SET - && SET_DEST (tmp) == pc_rtx - && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE - && GET_CODE (XEXP (SET_SRC (tmp), 0)) == NE - && GET_CODE (XEXP (XEXP (SET_SRC (tmp), 0), 0)) == REG - && REGNO (XEXP (XEXP (SET_SRC (tmp), 0), 0)) == 0) - { - fbranch_count++; - continue; - } - } - - - /* Find all floating point compare + branch insns. If possible, - reverse the comparison & the branch to avoid add,tr insns. */ - for (insn = insns; insn; insn = next_insn (insn)) - { - rtx tmp, next; - - /* Ignore anything that isn't an INSN. */ - if (GET_CODE (insn) != INSN) - continue; - - tmp = PATTERN (insn); - - /* It must be a set. */ - if (GET_CODE (tmp) != SET) - continue; - - /* The destination must be CCFP, which is register zero. */ - tmp = SET_DEST (tmp); - if (GET_CODE (tmp) != REG || REGNO (tmp) != 0) - continue; - - /* INSN should be a set of CCFP. - - See if the result of this insn is used in a reversed FP - conditional branch. If so, reverse our condition and - the branch. Doing so avoids useless add,tr insns. */ - next = next_insn (insn); - while (next) - { - /* Jumps, calls and labels stop our search. */ - if (GET_CODE (next) == JUMP_INSN - || GET_CODE (next) == CALL_INSN - || GET_CODE (next) == CODE_LABEL) - break; - - /* As does another fcmp insn. */ - if (GET_CODE (next) == INSN - && GET_CODE (PATTERN (next)) == SET - && GET_CODE (SET_DEST (PATTERN (next))) == REG - && REGNO (SET_DEST (PATTERN (next))) == 0) - break; - - next = next_insn (next); - } - - /* Is NEXT_INSN a branch? */ - if (next - && GET_CODE (next) == JUMP_INSN) - { - rtx pattern = PATTERN (next); - - /* If it a reversed fp conditional branch (eg uses add,tr) - and CCFP dies, then reverse our conditional and the branch - to avoid the add,tr. */ - if (GET_CODE (pattern) == SET - && SET_DEST (pattern) == pc_rtx - && GET_CODE (SET_SRC (pattern)) == IF_THEN_ELSE - && GET_CODE (XEXP (SET_SRC (pattern), 0)) == NE - && GET_CODE (XEXP (XEXP (SET_SRC (pattern), 0), 0)) == REG - && REGNO (XEXP (XEXP (SET_SRC (pattern), 0), 0)) == 0 - && GET_CODE (XEXP (SET_SRC (pattern), 1)) == PC - && (fcmp_count == fbranch_count - || (check_notes - && find_regno_note (next, REG_DEAD, 0)))) - { - /* Reverse the branch. */ - tmp = XEXP (SET_SRC (pattern), 1); - XEXP (SET_SRC (pattern), 1) = XEXP (SET_SRC (pattern), 2); - XEXP (SET_SRC (pattern), 2) = tmp; - INSN_CODE (next) = -1; - - /* Reverse our condition. */ - tmp = PATTERN (insn); - PUT_CODE (XEXP (tmp, 1), - reverse_condition (GET_CODE (XEXP (tmp, 1)))); - } - } - } - } - - pass = !pass; - -} - -/* You may have trouble believing this, but this is the HP-PA stack - layout. Wow. - - Offset Contents - - Variable arguments (optional; any number may be allocated) - - SP-(4*(N+9)) arg word N - : : - SP-56 arg word 5 - SP-52 arg word 4 - - Fixed arguments (must be allocated; may remain unused) - - SP-48 arg word 3 - SP-44 arg word 2 - SP-40 arg word 1 - SP-36 arg word 0 - - Frame Marker - - SP-32 External Data Pointer (DP) - SP-28 External sr4 - SP-24 External/stub RP (RP') - SP-20 Current RP - SP-16 Static Link - SP-12 Clean up - SP-8 Calling Stub RP (RP'') - SP-4 Previous SP - - Top of Frame - - SP-0 Stack Pointer (points to next available address) - -*/ - -/* This function saves registers as follows. Registers marked with ' are - this function's registers (as opposed to the previous function's). - If a frame_pointer isn't needed, r4 is saved as a general register; - the space for the frame pointer is still allocated, though, to keep - things simple. - - - Top of Frame - - SP (FP') Previous FP - SP + 4 Alignment filler (sigh) - SP + 8 Space for locals reserved here. - . - . - . - SP + n All call saved register used. - . - . - . - SP + o All call saved fp registers used. - . - . - . - SP + p (SP') points to next available address. - -*/ - -/* Emit RTL to store REG at the memory location specified by BASE+DISP. - Handle case where DISP > 8k by using the add_high_const pattern. - - Note in DISP > 8k case, we will leave the high part of the address - in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/ -static void -store_reg (reg, disp, base) - int reg, disp, base; -{ - if (VAL_14_BITS_P (disp)) - { - emit_move_insn (gen_rtx_MEM (SImode, - gen_rtx_PLUS (SImode, - gen_rtx_REG (SImode, base), - GEN_INT (disp))), - gen_rtx_REG (SImode, reg)); - } - else - { - emit_insn (gen_add_high_const (gen_rtx_REG (SImode, 1), - gen_rtx_REG (SImode, base), - GEN_INT (disp))); - emit_move_insn (gen_rtx_MEM (SImode, - gen_rtx_LO_SUM (SImode, - gen_rtx_REG (SImode, 1), - GEN_INT (disp))), - gen_rtx_REG (SImode, reg)); - } -} - -/* Emit RTL to load REG from the memory location specified by BASE+DISP. - Handle case where DISP > 8k by using the add_high_const pattern. - - Note in DISP > 8k case, we will leave the high part of the address - in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/ -static void -load_reg (reg, disp, base) - int reg, disp, base; -{ - if (VAL_14_BITS_P (disp)) - { - emit_move_insn (gen_rtx_REG (SImode, reg), - gen_rtx_MEM (SImode, - gen_rtx_PLUS (SImode, - gen_rtx_REG (SImode, base), - GEN_INT (disp)))); - } - else - { - emit_insn (gen_add_high_const (gen_rtx_REG (SImode, 1), - gen_rtx_REG (SImode, base), - GEN_INT (disp))); - emit_move_insn (gen_rtx_REG (SImode, reg), - gen_rtx_MEM (SImode, - gen_rtx_LO_SUM (SImode, - gen_rtx_REG (SImode, 1), - GEN_INT (disp)))); - } -} - -/* Emit RTL to set REG to the value specified by BASE+DISP. - Handle case where DISP > 8k by using the add_high_const pattern. - - Note in DISP > 8k case, we will leave the high part of the address - in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/ -static void -set_reg_plus_d(reg, base, disp) - int reg, base, disp; -{ - if (VAL_14_BITS_P (disp)) - { - emit_move_insn (gen_rtx_REG (SImode, reg), - gen_rtx_PLUS (SImode, - gen_rtx_REG (SImode, base), - GEN_INT (disp))); - } - else - { - emit_insn (gen_add_high_const (gen_rtx_REG (SImode, 1), - gen_rtx_REG (SImode, base), - GEN_INT (disp))); - emit_move_insn (gen_rtx_REG (SImode, reg), - gen_rtx_LO_SUM (SImode, - gen_rtx_REG (SImode, 1), - GEN_INT (disp))); - } -} - -/* Global variables set by FUNCTION_PROLOGUE. */ -/* Size of frame. Need to know this to emit return insns from - leaf procedures. */ -static int actual_fsize; -static int local_fsize, save_fregs; - -int -compute_frame_size (size, fregs_live) - int size; - int *fregs_live; -{ - extern int current_function_outgoing_args_size; - int i, fsize; - - /* 8 is space for frame pointer + filler. If any frame is allocated - we need to add this in because of STARTING_FRAME_OFFSET. */ - fsize = size + (size || frame_pointer_needed ? 8 : 0); - - /* We must leave enough space for all the callee saved registers - from 3 .. highest used callee save register since we don't - know if we're going to have an inline or out of line prologue - and epilogue. */ - for (i = 18; i >= 3; i--) - if (regs_ever_live[i]) - { - fsize += 4 * (i - 2); - break; - } - - /* Round the stack. */ - fsize = (fsize + 7) & ~7; - - /* We must leave enough space for all the callee saved registers - from 3 .. highest used callee save register since we don't - know if we're going to have an inline or out of line prologue - and epilogue. */ - for (i = 66; i >= 48; i -= 2) - if (regs_ever_live[i] || regs_ever_live[i + 1]) - { - if (fregs_live) - *fregs_live = 1; - - fsize += 4 * (i - 46); - break; - } - - fsize += current_function_outgoing_args_size; - if (! leaf_function_p () || fsize) - fsize += 32; - return (fsize + 63) & ~63; -} - -rtx hp_profile_label_rtx; -static char hp_profile_label_name[8]; -void -output_function_prologue (file, size) - FILE *file; - int size ATTRIBUTE_UNUSED; -{ - /* The function's label and associated .PROC must never be - separated and must be output *after* any profiling declarations - to avoid changing spaces/subspaces within a procedure. */ - ASM_OUTPUT_LABEL (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); - fputs ("\t.PROC\n", file); - - /* hppa_expand_prologue does the dirty work now. We just need - to output the assembler directives which denote the start - of a function. */ - fprintf (file, "\t.CALLINFO FRAME=%d", actual_fsize); - if (regs_ever_live[2] || profile_flag) - fputs (",CALLS,SAVE_RP", file); - else - fputs (",NO_CALLS", file); - - if (frame_pointer_needed) - fputs (",SAVE_SP", file); - - /* Pass on information about the number of callee register saves - performed in the prologue. - - The compiler is supposed to pass the highest register number - saved, the assembler then has to adjust that number before - entering it into the unwind descriptor (to account for any - caller saved registers with lower register numbers than the - first callee saved register). */ - if (gr_saved) - fprintf (file, ",ENTRY_GR=%d", gr_saved + 2); - - if (fr_saved) - fprintf (file, ",ENTRY_FR=%d", fr_saved + 11); - - fputs ("\n\t.ENTRY\n", file); - - /* Horrid hack. emit_function_prologue will modify this RTL in - place to get the expected results. */ - if (profile_flag) - ASM_GENERATE_INTERNAL_LABEL (hp_profile_label_name, "LP", - hp_profile_labelno); - - /* If we're using GAS and not using the portable runtime model, then - we don't need to accumulate the total number of code bytes. */ - if (TARGET_GAS && ! TARGET_PORTABLE_RUNTIME) - total_code_bytes = 0; - else if (insn_addresses) - { - unsigned int old_total = total_code_bytes; - - total_code_bytes += insn_addresses[INSN_UID (get_last_insn())]; - total_code_bytes += FUNCTION_BOUNDARY / BITS_PER_UNIT; - - /* Be prepared to handle overflows. */ - total_code_bytes = old_total > total_code_bytes ? -1 : total_code_bytes; - } - else - total_code_bytes = -1; - - remove_useless_addtr_insns (get_insns (), 0); - - /* Restore INSN_CODEs for insn which use unscaled indexed addresses. */ - restore_unscaled_index_insn_codes (get_insns ()); -} - -void -hppa_expand_prologue() -{ - extern char call_used_regs[]; - int size = get_frame_size (); - int merge_sp_adjust_with_store = 0; - int i, offset; - rtx tmpreg, size_rtx; - - gr_saved = 0; - fr_saved = 0; - save_fregs = 0; - local_fsize = size + (size || frame_pointer_needed ? 8 : 0); - actual_fsize = compute_frame_size (size, &save_fregs); - - /* Compute a few things we will use often. */ - tmpreg = gen_rtx_REG (SImode, 1); - size_rtx = GEN_INT (actual_fsize); - - /* Handle out of line prologues and epilogues. */ - if (TARGET_SPACE) - { - rtx operands[2]; - int saves = 0; - int outline_insn_count = 0; - int inline_insn_count = 0; - - /* Count the number of insns for the inline and out of line - variants so we can choose one appropriately. - - No need to screw with counting actual_fsize operations -- they're - done for both inline and out of line prologues. */ - if (regs_ever_live[2]) - inline_insn_count += 1; - - if (! cint_ok_for_move (local_fsize)) - outline_insn_count += 2; - else - outline_insn_count += 1; - - /* Put the register save info into %r22. */ - for (i = 18; i >= 3; i--) - if (regs_ever_live[i] && ! call_used_regs[i]) - { - /* -1 because the stack adjustment is normally done in - the same insn as a register save. */ - inline_insn_count += (i - 2) - 1; - saves = i; - break; - } - - for (i = 66; i >= 48; i -= 2) - if (regs_ever_live[i] || regs_ever_live[i + 1]) - { - /* +1 needed as we load %r1 with the start of the freg - save area. */ - inline_insn_count += (i/2 - 23) + 1; - saves |= ((i/2 - 12 ) << 16); - break; - } - - if (frame_pointer_needed) - inline_insn_count += 3; - - if (! cint_ok_for_move (saves)) - outline_insn_count += 2; - else - outline_insn_count += 1; - - if (TARGET_PORTABLE_RUNTIME) - outline_insn_count += 2; - else - outline_insn_count += 1; - - /* If there's a lot of insns in the prologue, then do it as - an out-of-line sequence. */ - if (inline_insn_count > outline_insn_count) - { - /* Put the local_fisze into %r19. */ - operands[0] = gen_rtx_REG (SImode, 19); - operands[1] = GEN_INT (local_fsize); - emit_move_insn (operands[0], operands[1]); - - /* Put the stack size into %r21. */ - operands[0] = gen_rtx_REG (SImode, 21); - operands[1] = size_rtx; - emit_move_insn (operands[0], operands[1]); - - operands[0] = gen_rtx_REG (SImode, 22); - operands[1] = GEN_INT (saves); - emit_move_insn (operands[0], operands[1]); - - /* Now call the out-of-line prologue. */ - emit_insn (gen_outline_prologue_call ()); - emit_insn (gen_blockage ()); - - /* Note that we're using an out-of-line prologue. */ - out_of_line_prologue_epilogue = 1; - return; - } - } - - out_of_line_prologue_epilogue = 0; - - /* Save RP first. The calling conventions manual states RP will - always be stored into the caller's frame at sp-20. */ - if (regs_ever_live[2] || profile_flag) - store_reg (2, -20, STACK_POINTER_REGNUM); - - /* Allocate the local frame and set up the frame pointer if needed. */ - if (actual_fsize) - { - if (frame_pointer_needed) - { - /* Copy the old frame pointer temporarily into %r1. Set up the - new stack pointer, then store away the saved old frame pointer - into the stack at sp+actual_fsize and at the same time update - the stack pointer by actual_fsize bytes. Two versions, first - handles small (<8k) frames. The second handles large (>8k) - frames. */ - emit_move_insn (tmpreg, frame_pointer_rtx); - emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); - if (VAL_14_BITS_P (actual_fsize)) - emit_insn (gen_post_stwm (stack_pointer_rtx, tmpreg, size_rtx)); - else - { - /* It is incorrect to store the saved frame pointer at *sp, - then increment sp (writes beyond the current stack boundary). - - So instead use stwm to store at *sp and post-increment the - stack pointer as an atomic operation. Then increment sp to - finish allocating the new frame. */ - emit_insn (gen_post_stwm (stack_pointer_rtx, tmpreg, GEN_INT (64))); - set_reg_plus_d (STACK_POINTER_REGNUM, - STACK_POINTER_REGNUM, - actual_fsize - 64); - } - } - /* no frame pointer needed. */ - else - { - /* In some cases we can perform the first callee register save - and allocating the stack frame at the same time. If so, just - make a note of it and defer allocating the frame until saving - the callee registers. */ - if (VAL_14_BITS_P (-actual_fsize) - && local_fsize == 0 - && ! profile_flag - && ! flag_pic) - merge_sp_adjust_with_store = 1; - /* Can not optimize. Adjust the stack frame by actual_fsize bytes. */ - else if (actual_fsize != 0) - set_reg_plus_d (STACK_POINTER_REGNUM, - STACK_POINTER_REGNUM, - actual_fsize); - } - } - - /* The hppa calling conventions say that %r19, the pic offset - register, is saved at sp - 32 (in this function's frame) when - generating PIC code. FIXME: What is the correct thing to do - for functions which make no calls and allocate no frame? Do - we need to allocate a frame, or can we just omit the save? For - now we'll just omit the save. */ - if (actual_fsize != 0 && flag_pic) - store_reg (PIC_OFFSET_TABLE_REGNUM, -32, STACK_POINTER_REGNUM); - - /* Profiling code. - - Instead of taking one argument, the counter label, as most normal - mcounts do, _mcount appears to behave differently on the HPPA. It - takes the return address of the caller, the address of this routine, - and the address of the label. Also, it isn't magic, so - argument registers have to be preserved. */ - if (profile_flag) - { - int pc_offset, i, arg_offset, basereg, offsetadj; - - pc_offset = 4 + (frame_pointer_needed - ? (VAL_14_BITS_P (actual_fsize) ? 12 : 20) - : (VAL_14_BITS_P (actual_fsize) ? 4 : 8)); - - /* When the function has a frame pointer, use it as the base - register for saving/restore registers. Else use the stack - pointer. Adjust the offset according to the frame size if - this function does not have a frame pointer. */ - - basereg = frame_pointer_needed ? FRAME_POINTER_REGNUM - : STACK_POINTER_REGNUM; - offsetadj = frame_pointer_needed ? 0 : actual_fsize; - - /* Horrid hack. emit_function_prologue will modify this RTL in - place to get the expected results. sprintf here is just to - put something in the name. */ - sprintf(hp_profile_label_name, "LP$%04d", -1); - hp_profile_label_rtx = gen_rtx_SYMBOL_REF (SImode, hp_profile_label_name); - if (current_function_returns_struct) - store_reg (STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg); - - for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4) - if (regs_ever_live [i]) - { - store_reg (i, arg_offset, basereg); - /* Deal with arg_offset not fitting in 14 bits. */ - pc_offset += VAL_14_BITS_P (arg_offset) ? 4 : 8; - } - - emit_move_insn (gen_rtx_REG (SImode, 26), gen_rtx_REG (SImode, 2)); - emit_move_insn (tmpreg, gen_rtx_HIGH (SImode, hp_profile_label_rtx)); - emit_move_insn (gen_rtx_REG (SImode, 24), - gen_rtx_LO_SUM (SImode, tmpreg, hp_profile_label_rtx)); - /* %r25 is set from within the output pattern. */ - emit_insn (gen_call_profiler (GEN_INT (- pc_offset - 20))); - - /* Restore argument registers. */ - for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4) - if (regs_ever_live [i]) - load_reg (i, arg_offset, basereg); - - if (current_function_returns_struct) - load_reg (STRUCT_VALUE_REGNUM, -12 - offsetadj, basereg); - - } - - /* Normal register save. - - Do not save the frame pointer in the frame_pointer_needed case. It - was done earlier. */ - if (frame_pointer_needed) - { - for (i = 18, offset = local_fsize; i >= 4; i--) - if (regs_ever_live[i] && ! call_used_regs[i]) - { - store_reg (i, offset, FRAME_POINTER_REGNUM); - offset += 4; - gr_saved++; - } - /* Account for %r3 which is saved in a special place. */ - gr_saved++; - } - /* No frame pointer needed. */ - else - { - for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--) - if (regs_ever_live[i] && ! call_used_regs[i]) - { - /* If merge_sp_adjust_with_store is nonzero, then we can - optimize the first GR save. */ - if (merge_sp_adjust_with_store) - { - merge_sp_adjust_with_store = 0; - emit_insn (gen_post_stwm (stack_pointer_rtx, - gen_rtx_REG (SImode, i), - GEN_INT (-offset))); - } - else - store_reg (i, offset, STACK_POINTER_REGNUM); - offset += 4; - gr_saved++; - } - - /* If we wanted to merge the SP adjustment with a GR save, but we never - did any GR saves, then just emit the adjustment here. */ - if (merge_sp_adjust_with_store) - set_reg_plus_d (STACK_POINTER_REGNUM, - STACK_POINTER_REGNUM, - actual_fsize); - } - - /* Align pointer properly (doubleword boundary). */ - offset = (offset + 7) & ~7; - - /* Floating point register store. */ - if (save_fregs) - { - /* First get the frame or stack pointer to the start of the FP register - save area. */ - if (frame_pointer_needed) - set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset); - else - set_reg_plus_d (1, STACK_POINTER_REGNUM, offset); - - /* Now actually save the FP registers. */ - for (i = 66; i >= 48; i -= 2) - { - if (regs_ever_live[i] || regs_ever_live[i + 1]) - { - emit_move_insn (gen_rtx_MEM (DFmode, - gen_rtx_POST_INC (DFmode, tmpreg)), - gen_rtx_REG (DFmode, i)); - fr_saved++; - } - } - } - - /* When generating PIC code it is necessary to save/restore the - PIC register around each function call. We used to do this - in the call patterns themselves, but that implementation - made incorrect assumptions about using global variables to hold - per-function rtl code generated in the backend. - - So instead, we copy the PIC register into a reserved callee saved - register in the prologue. Then after each call we reload the PIC - register from the callee saved register. We also reload the PIC - register from the callee saved register in the epilogue ensure the - PIC register is valid at function exit. - - This may (depending on the exact characteristics of the function) - even be more efficient. - - Avoid this if the callee saved register wasn't used (these are - leaf functions). */ - if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM_SAVED]) - emit_move_insn (gen_rtx_REG (SImode, PIC_OFFSET_TABLE_REGNUM_SAVED), - gen_rtx_REG (SImode, PIC_OFFSET_TABLE_REGNUM)); -} - - -void -output_function_epilogue (file, size) - FILE *file; - int size ATTRIBUTE_UNUSED; -{ - rtx insn = get_last_insn (); - - /* hppa_expand_epilogue does the dirty work now. We just need - to output the assembler directives which denote the end - of a function. - - To make debuggers happy, emit a nop if the epilogue was completely - eliminated due to a volatile call as the last insn in the - current function. That way the return address (in %r2) will - always point to a valid instruction in the current function. */ - - /* Get the last real insn. */ - if (GET_CODE (insn) == NOTE) - insn = prev_real_insn (insn); - - /* If it is a sequence, then look inside. */ - if (insn && GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE) - insn = XVECEXP (PATTERN (insn), 0, 0); - - /* If insn is a CALL_INSN, then it must be a call to a volatile - function (otherwise there would be epilogue insns). */ - if (insn && GET_CODE (insn) == CALL_INSN) - fputs ("\tnop\n", file); - - fputs ("\t.EXIT\n\t.PROCEND\n", file); - - /* Free up stuff we don't need anymore. */ - if (unscaled_index_insn_codes) - free (unscaled_index_insn_codes); - max_unscaled_index_insn_codes_uid = 0; -} - -void -hppa_expand_epilogue () -{ - rtx tmpreg; - int offset,i; - int merge_sp_adjust_with_load = 0; - - /* Handle out of line prologues and epilogues. */ - if (TARGET_SPACE && out_of_line_prologue_epilogue) - { - int saves = 0; - rtx operands[2]; - - /* Put the register save info into %r22. */ - for (i = 18; i >= 3; i--) - if (regs_ever_live[i] && ! call_used_regs[i]) - { - saves = i; - break; - } - - for (i = 66; i >= 48; i -= 2) - if (regs_ever_live[i] || regs_ever_live[i + 1]) - { - saves |= ((i/2 - 12 ) << 16); - break; - } - - emit_insn (gen_blockage ()); - - /* Put the local_fisze into %r19. */ - operands[0] = gen_rtx_REG (SImode, 19); - operands[1] = GEN_INT (local_fsize); - emit_move_insn (operands[0], operands[1]); - - /* Put the stack size into %r21. */ - operands[0] = gen_rtx_REG (SImode, 21); - operands[1] = GEN_INT (actual_fsize); - emit_move_insn (operands[0], operands[1]); - - operands[0] = gen_rtx_REG (SImode, 22); - operands[1] = GEN_INT (saves); - emit_move_insn (operands[0], operands[1]); - - /* Now call the out-of-line epilogue. */ - emit_insn (gen_outline_epilogue_call ()); - return; - } - - /* We will use this often. */ - tmpreg = gen_rtx_REG (SImode, 1); - - /* Try to restore RP early to avoid load/use interlocks when - RP gets used in the return (bv) instruction. This appears to still - be necessary even when we schedule the prologue and epilogue. */ - if (frame_pointer_needed - && (regs_ever_live [2] || profile_flag)) - load_reg (2, -20, FRAME_POINTER_REGNUM); - - /* No frame pointer, and stack is smaller than 8k. */ - else if (! frame_pointer_needed - && VAL_14_BITS_P (actual_fsize + 20) - && (regs_ever_live[2] || profile_flag)) - load_reg (2, - (actual_fsize + 20), STACK_POINTER_REGNUM); - - /* General register restores. */ - if (frame_pointer_needed) - { - for (i = 18, offset = local_fsize; i >= 4; i--) - if (regs_ever_live[i] && ! call_used_regs[i]) - { - load_reg (i, offset, FRAME_POINTER_REGNUM); - offset += 4; - } - } - else - { - for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--) - { - if (regs_ever_live[i] && ! call_used_regs[i]) - { - /* Only for the first load. - merge_sp_adjust_with_load holds the register load - with which we will merge the sp adjustment. */ - if (VAL_14_BITS_P (actual_fsize + 20) - && local_fsize == 0 - && ! merge_sp_adjust_with_load) - merge_sp_adjust_with_load = i; - else - load_reg (i, offset, STACK_POINTER_REGNUM); - offset += 4; - } - } - } - - /* Align pointer properly (doubleword boundary). */ - offset = (offset + 7) & ~7; - - /* FP register restores. */ - if (save_fregs) - { - /* Adjust the register to index off of. */ - if (frame_pointer_needed) - set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset); - else - set_reg_plus_d (1, STACK_POINTER_REGNUM, offset); - - /* Actually do the restores now. */ - for (i = 66; i >= 48; i -= 2) - { - if (regs_ever_live[i] || regs_ever_live[i + 1]) - { - emit_move_insn (gen_rtx_REG (DFmode, i), - gen_rtx_MEM (DFmode, - gen_rtx_POST_INC (DFmode, tmpreg))); - } - } - } - - /* Emit a blockage insn here to keep these insns from being moved to - an earlier spot in the epilogue, or into the main instruction stream. - - This is necessary as we must not cut the stack back before all the - restores are finished. */ - emit_insn (gen_blockage ()); - /* No frame pointer, but we have a stack greater than 8k. We restore - %r2 very late in this case. (All other cases are restored as early - as possible.) */ - if (! frame_pointer_needed - && ! VAL_14_BITS_P (actual_fsize + 20) - && (regs_ever_live[2] || profile_flag)) - { - set_reg_plus_d (STACK_POINTER_REGNUM, - STACK_POINTER_REGNUM, - - actual_fsize); - - /* This used to try and be clever by not depending on the value in - %r30 and instead use the value held in %r1 (so that the 2nd insn - which sets %r30 could be put in the delay slot of the return insn). - - That won't work since if the stack is exactly 8k set_reg_plus_d - doesn't set %r1, just %r30. */ - load_reg (2, - 20, STACK_POINTER_REGNUM); - } - - /* Reset stack pointer (and possibly frame pointer). The stack - pointer is initially set to fp + 64 to avoid a race condition. */ - else if (frame_pointer_needed) - { - set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64); - emit_insn (gen_pre_ldwm (frame_pointer_rtx, - stack_pointer_rtx, - GEN_INT (-64))); - } - /* If we were deferring a callee register restore, do it now. */ - else if (! frame_pointer_needed && merge_sp_adjust_with_load) - emit_insn (gen_pre_ldwm (gen_rtx_REG (SImode, merge_sp_adjust_with_load), - stack_pointer_rtx, - GEN_INT (- actual_fsize))); - else if (actual_fsize != 0) - set_reg_plus_d (STACK_POINTER_REGNUM, - STACK_POINTER_REGNUM, - - actual_fsize); -} - -/* Fetch the return address for the frame COUNT steps up from - the current frame, after the prologue. FRAMEADDR is the - frame pointer of the COUNT frame. - - We want to ignore any export stub remnants here. - - The value returned is used in two different ways: - - 1. To find a function's caller. - - 2. To change the return address for a function. - - This function handles most instances of case 1; however, it will - fail if there are two levels of stubs to execute on the return - path. The only way I believe that can happen is if the return value - needs a parameter relocation, which never happens for C code. - - This function handles most instances of case 2; however, it will - fail if we did not originally have stub code on the return path - but will need code on the new return path. This can happen if - the caller & callee are both in the main program, but the new - return location is in a shared library. - - To handle this correctly we need to set the return pointer at - frame-20 to point to a return stub frame-24 to point to the - location we wish to return to. */ - -rtx -return_addr_rtx (count, frameaddr) - int count ATTRIBUTE_UNUSED; - rtx frameaddr; -{ - rtx label; - rtx saved_rp; - rtx ins; - - saved_rp = gen_reg_rtx (Pmode); - - /* First, we start off with the normal return address pointer from - -20[frameaddr]. */ - - emit_move_insn (saved_rp, plus_constant (frameaddr, -5 * UNITS_PER_WORD)); - - /* Get pointer to the instruction stream. We have to mask out the - privilege level from the two low order bits of the return address - pointer here so that ins will point to the start of the first - instruction that would have been executed if we returned. */ - ins = copy_to_reg (gen_rtx_AND (Pmode, - copy_to_reg (gen_rtx_MEM (Pmode, saved_rp)), - MASK_RETURN_ADDR)); - label = gen_label_rtx (); - - /* Check the instruction stream at the normal return address for the - export stub: - - 0x4bc23fd1 | stub+8: ldw -18(sr0,sp),rp - 0x004010a1 | stub+12: ldsid (sr0,rp),r1 - 0x00011820 | stub+16: mtsp r1,sr0 - 0xe0400002 | stub+20: be,n 0(sr0,rp) - - If it is an export stub, than our return address is really in - -24[frameaddr]. */ - - emit_cmp_insn (gen_rtx_MEM (SImode, ins), - GEN_INT (0x4bc23fd1), - NE, NULL_RTX, SImode, 1, 0); - emit_jump_insn (gen_bne (label)); - - emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 4)), - GEN_INT (0x004010a1), - NE, NULL_RTX, SImode, 1, 0); - emit_jump_insn (gen_bne (label)); - - emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 8)), - GEN_INT (0x00011820), - NE, NULL_RTX, SImode, 1, 0); - emit_jump_insn (gen_bne (label)); - - emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 12)), - GEN_INT (0xe0400002), - NE, NULL_RTX, SImode, 1, 0); - - /* If there is no export stub then just use our initial guess of - -20[frameaddr]. */ - - emit_jump_insn (gen_bne (label)); - - /* Here we know that our return address pointer points to an export - stub. We don't want to return the address of the export stub, - but rather the return address that leads back into user code. - That return address is stored at -24[frameaddr]. */ - - emit_move_insn (saved_rp, plus_constant (frameaddr, -6 * UNITS_PER_WORD)); - - emit_label (label); - return gen_rtx_MEM (Pmode, memory_address (Pmode, saved_rp)); -} - -/* This is only valid once reload has completed because it depends on - knowing exactly how much (if any) frame there is and... - - It's only valid if there is no frame marker to de-allocate and... - - It's only valid if %r2 hasn't been saved into the caller's frame - (we're not profiling and %r2 isn't live anywhere). */ -int -hppa_can_use_return_insn_p () -{ - return (reload_completed - && (compute_frame_size (get_frame_size (), 0) ? 0 : 1) - && ! profile_flag - && ! regs_ever_live[2] - && ! frame_pointer_needed); -} - -void -emit_bcond_fp (code, operand0) - enum rtx_code code; - rtx operand0; -{ - emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, - gen_rtx_IF_THEN_ELSE (VOIDmode, - gen_rtx_fmt_ee (code, - VOIDmode, - gen_rtx_REG (CCFPmode, 0), - const0_rtx), - gen_rtx_LABEL_REF (VOIDmode, operand0), - pc_rtx))); - -} - -rtx -gen_cmp_fp (code, operand0, operand1) - enum rtx_code code; - rtx operand0, operand1; -{ - return gen_rtx_SET (VOIDmode, gen_rtx_REG (CCFPmode, 0), - gen_rtx_fmt_ee (code, CCFPmode, operand0, operand1)); -} - -/* Adjust the cost of a scheduling dependency. Return the new cost of - a dependency LINK or INSN on DEP_INSN. COST is the current cost. */ - -int -pa_adjust_cost (insn, link, dep_insn, cost) - rtx insn; - rtx link; - rtx dep_insn; - int cost; -{ - enum attr_type attr_type; - - if (! recog_memoized (insn)) - return 0; - - /* CYGNUS LOCAL PA8000/law */ - /* No cost adjustments are needed for the PA8000 */ - if (pa_cpu == PROCESSOR_8000) - return 0; - /* END CYGNUS LOCAL */ - - attr_type = get_attr_type (insn); - - if (REG_NOTE_KIND (link) == 0) - { - /* Data dependency; DEP_INSN writes a register that INSN reads some - cycles later. */ - - if (attr_type == TYPE_FPSTORE) - { - rtx pat = PATTERN (insn); - rtx dep_pat = PATTERN (dep_insn); - if (GET_CODE (pat) == PARALLEL) - { - /* This happens for the fstXs,mb patterns. */ - pat = XVECEXP (pat, 0, 0); - } - if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) - /* If this happens, we have to extend this to schedule - optimally. Return 0 for now. */ - return 0; - - if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat))) - { - if (! recog_memoized (dep_insn)) - return 0; - /* DEP_INSN is writing its result to the register - being stored in the fpstore INSN. */ - switch (get_attr_type (dep_insn)) - { - case TYPE_FPLOAD: - /* This cost 3 cycles, not 2 as the md says for the - 700 and 7100. */ - return cost + 1; - - case TYPE_FPALU: - case TYPE_FPMULSGL: - case TYPE_FPMULDBL: - case TYPE_FPDIVSGL: - case TYPE_FPDIVDBL: - case TYPE_FPSQRTSGL: - case TYPE_FPSQRTDBL: - /* In these important cases, we save one cycle compared to - when flop instruction feed each other. */ - return cost - 1; - - default: - return cost; - } - } - } - - /* For other data dependencies, the default cost specified in the - md is correct. */ - return cost; - } - else if (REG_NOTE_KIND (link) == REG_DEP_ANTI) - { - /* Anti dependency; DEP_INSN reads a register that INSN writes some - cycles later. */ - - if (attr_type == TYPE_FPLOAD) - { - rtx pat = PATTERN (insn); - rtx dep_pat = PATTERN (dep_insn); - if (GET_CODE (pat) == PARALLEL) - { - /* This happens for the fldXs,mb patterns. */ - pat = XVECEXP (pat, 0, 0); - } - if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) - /* If this happens, we have to extend this to schedule - optimally. Return 0 for now. */ - return 0; - - if (reg_mentioned_p (SET_DEST (pat), SET_SRC (dep_pat))) - { - if (! recog_memoized (dep_insn)) - return 0; - switch (get_attr_type (dep_insn)) - { - case TYPE_FPALU: - case TYPE_FPMULSGL: - case TYPE_FPMULDBL: - case TYPE_FPDIVSGL: - case TYPE_FPDIVDBL: - case TYPE_FPSQRTSGL: - case TYPE_FPSQRTDBL: - /* A fpload can't be issued until one cycle before a - preceding arithmetic operation has finished if - the target of the fpload is any of the sources - (or destination) of the arithmetic operation. */ - return cost - 1; - - default: - return 0; - } - } - } - else if (attr_type == TYPE_FPALU) - { - rtx pat = PATTERN (insn); - rtx dep_pat = PATTERN (dep_insn); - if (GET_CODE (pat) == PARALLEL) - { - /* This happens for the fldXs,mb patterns. */ - pat = XVECEXP (pat, 0, 0); - } - if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) - /* If this happens, we have to extend this to schedule - optimally. Return 0 for now. */ - return 0; - - if (reg_mentioned_p (SET_DEST (pat), SET_SRC (dep_pat))) - { - if (! recog_memoized (dep_insn)) - return 0; - switch (get_attr_type (dep_insn)) - { - case TYPE_FPDIVSGL: - case TYPE_FPDIVDBL: - case TYPE_FPSQRTSGL: - case TYPE_FPSQRTDBL: - /* An ALU flop can't be issued until two cycles before a - preceding divide or sqrt operation has finished if - the target of the ALU flop is any of the sources - (or destination) of the divide or sqrt operation. */ - return cost - 2; - - default: - return 0; - } - } - } - - /* For other anti dependencies, the cost is 0. */ - return 0; - } - else if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT) - { - /* Output dependency; DEP_INSN writes a register that INSN writes some - cycles later. */ - if (attr_type == TYPE_FPLOAD) - { - rtx pat = PATTERN (insn); - rtx dep_pat = PATTERN (dep_insn); - if (GET_CODE (pat) == PARALLEL) - { - /* This happens for the fldXs,mb patterns. */ - pat = XVECEXP (pat, 0, 0); - } - if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) - /* If this happens, we have to extend this to schedule - optimally. Return 0 for now. */ - return 0; - - if (reg_mentioned_p (SET_DEST (pat), SET_DEST (dep_pat))) - { - if (! recog_memoized (dep_insn)) - return 0; - switch (get_attr_type (dep_insn)) - { - case TYPE_FPALU: - case TYPE_FPMULSGL: - case TYPE_FPMULDBL: - case TYPE_FPDIVSGL: - case TYPE_FPDIVDBL: - case TYPE_FPSQRTSGL: - case TYPE_FPSQRTDBL: - /* A fpload can't be issued until one cycle before a - preceding arithmetic operation has finished if - the target of the fpload is the destination of the - arithmetic operation. */ - return cost - 1; - - default: - return 0; - } - } - } - else if (attr_type == TYPE_FPALU) - { - rtx pat = PATTERN (insn); - rtx dep_pat = PATTERN (dep_insn); - if (GET_CODE (pat) == PARALLEL) - { - /* This happens for the fldXs,mb patterns. */ - pat = XVECEXP (pat, 0, 0); - } - if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) - /* If this happens, we have to extend this to schedule - optimally. Return 0 for now. */ - return 0; - - if (reg_mentioned_p (SET_DEST (pat), SET_DEST (dep_pat))) - { - if (! recog_memoized (dep_insn)) - return 0; - switch (get_attr_type (dep_insn)) - { - case TYPE_FPDIVSGL: - case TYPE_FPDIVDBL: - case TYPE_FPSQRTSGL: - case TYPE_FPSQRTDBL: - /* An ALU flop can't be issued until two cycles before a - preceding divide or sqrt operation has finished if - the target of the ALU flop is also the target of - the divide or sqrt operation. */ - return cost - 2; - - default: - return 0; - } - } - } - - /* For other output dependencies, the cost is 0. */ - return 0; - } - else - abort (); -} - -/* Return any length adjustment needed by INSN which already has its length - computed as LENGTH. Return zero if no adjustment is necessary. - - For the PA: function calls, millicode calls, and backwards short - conditional branches with unfilled delay slots need an adjustment by +1 - (to account for the NOP which will be inserted into the instruction stream). - - Also compute the length of an inline block move here as it is too - complicated to express as a length attribute in pa.md. */ -int -pa_adjust_insn_length (insn, length) - rtx insn; - int length; -{ - rtx pat = PATTERN (insn); - - /* Call insns which are *not* indirect and have unfilled delay slots. */ - if (GET_CODE (insn) == CALL_INSN) - { - - if (GET_CODE (XVECEXP (pat, 0, 0)) == CALL - && GET_CODE (XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0)) == SYMBOL_REF) - return 4; - else if (GET_CODE (XVECEXP (pat, 0, 0)) == SET - && GET_CODE (XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0)) - == SYMBOL_REF) - return 4; - else - return 0; - } - /* Jumps inside switch tables which have unfilled delay slots - also need adjustment. */ - else if (GET_CODE (insn) == JUMP_INSN - && simplejump_p (insn) - && GET_MODE (insn) == SImode) - return 4; - /* Millicode insn with an unfilled delay slot. */ - else if (GET_CODE (insn) == INSN - && GET_CODE (pat) != SEQUENCE - && GET_CODE (pat) != USE - && GET_CODE (pat) != CLOBBER - && get_attr_type (insn) == TYPE_MILLI) - return 4; - /* Block move pattern. */ - else if (GET_CODE (insn) == INSN - && GET_CODE (pat) == PARALLEL - && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 0)) == MEM - && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 1)) == MEM - && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 0)) == BLKmode - && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 1)) == BLKmode) - return compute_movstrsi_length (insn) - 4; - /* Conditional branch with an unfilled delay slot. */ - else if (GET_CODE (insn) == JUMP_INSN && ! simplejump_p (insn)) - { - /* Adjust a short backwards conditional with an unfilled delay slot. */ - if (GET_CODE (pat) == SET - && length == 4 - && ! forward_branch_p (insn)) - return 4; - else if (GET_CODE (pat) == PARALLEL - && get_attr_type (insn) == TYPE_PARALLEL_BRANCH - && length == 4) - return 4; - /* Adjust dbra insn with short backwards conditional branch with - unfilled delay slot -- only for case where counter is in a - general register register. */ - else if (GET_CODE (pat) == PARALLEL - && GET_CODE (XVECEXP (pat, 0, 1)) == SET - && GET_CODE (XEXP (XVECEXP (pat, 0, 1), 0)) == REG - && ! FP_REG_P (XEXP (XVECEXP (pat, 0, 1), 0)) - && length == 4 - && ! forward_branch_p (insn)) - return 4; - else - return 0; - } - return 0; -} - -/* Print operand X (an rtx) in assembler syntax to file FILE. - CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. - For `%' followed by punctuation, CODE is the punctuation and X is null. */ - -void -print_operand (file, x, code) - FILE *file; - rtx x; - int code; -{ - switch (code) - { - case '#': - /* Output a 'nop' if there's nothing for the delay slot. */ - if (dbr_sequence_length () == 0) - fputs ("\n\tnop", file); - return; - case '*': - /* Output an nullification completer if there's nothing for the */ - /* delay slot or nullification is requested. */ - if (dbr_sequence_length () == 0 || - (final_sequence && - INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))) - fputs (",n", file); - return; - case 'R': - /* Print out the second register name of a register pair. - I.e., R (6) => 7. */ - fputs (reg_names[REGNO (x)+1], file); - return; - case 'r': - /* A register or zero. */ - if (x == const0_rtx - || (x == CONST0_RTX (DFmode)) - || (x == CONST0_RTX (SFmode))) - { - fputs ("0", file); - return; - } - else - break; - case 'C': /* Plain (C)ondition */ - case 'X': - switch (GET_CODE (x)) - { - case EQ: - fputs ("=", file); break; - case NE: - fputs ("<>", file); break; - case GT: - fputs (">", file); break; - case GE: - fputs (">=", file); break; - case GEU: - fputs (">>=", file); break; - case GTU: - fputs (">>", file); break; - case LT: - fputs ("<", file); break; - case LE: - fputs ("<=", file); break; - case LEU: - fputs ("<<=", file); break; - case LTU: - fputs ("<<", file); break; - default: - abort (); - } - return; - case 'N': /* Condition, (N)egated */ - switch (GET_CODE (x)) - { - case EQ: - fputs ("<>", file); break; - case NE: - fputs ("=", file); break; - case GT: - fputs ("<=", file); break; - case GE: - fputs ("<", file); break; - case GEU: - fputs ("<<", file); break; - case GTU: - fputs ("<<=", file); break; - case LT: - fputs (">=", file); break; - case LE: - fputs (">", file); break; - case LEU: - fputs (">>", file); break; - case LTU: - fputs (">>=", file); break; - default: - abort (); - } - return; - /* For floating point comparisons. Need special conditions to deal - with NaNs properly. */ - case 'Y': - switch (GET_CODE (x)) - { - case EQ: - fputs ("!=", file); break; - case NE: - fputs ("=", file); break; - case GT: - fputs ("<=", file); break; - case GE: - fputs ("<", file); break; - case LT: - fputs (">=", file); break; - case LE: - fputs (">", file); break; - default: - abort (); - } - return; - case 'S': /* Condition, operands are (S)wapped. */ - switch (GET_CODE (x)) - { - case EQ: - fputs ("=", file); break; - case NE: - fputs ("<>", file); break; - case GT: - fputs ("<", file); break; - case GE: - fputs ("<=", file); break; - case GEU: - fputs ("<<=", file); break; - case GTU: - fputs ("<<", file); break; - case LT: - fputs (">", file); break; - case LE: - fputs (">=", file); break; - case LEU: - fputs (">>=", file); break; - case LTU: - fputs (">>", file); break; - default: - abort (); - } - return; - case 'B': /* Condition, (B)oth swapped and negate. */ - switch (GET_CODE (x)) - { - case EQ: - fputs ("<>", file); break; - case NE: - fputs ("=", file); break; - case GT: - fputs (">=", file); break; - case GE: - fputs (">", file); break; - case GEU: - fputs (">>", file); break; - case GTU: - fputs (">>=", file); break; - case LT: - fputs ("<=", file); break; - case LE: - fputs ("<", file); break; - case LEU: - fputs ("<<", file); break; - case LTU: - fputs ("<<=", file); break; - default: - abort (); - } - return; - case 'k': - if (GET_CODE (x) == CONST_INT) - { - fprintf (file, "%d", ~INTVAL (x)); - return; - } - abort(); - case 'L': - if (GET_CODE (x) == CONST_INT) - { - fprintf (file, "%d", 32 - (INTVAL (x) & 31)); - return; - } - abort(); - case 'O': - if (GET_CODE (x) == CONST_INT && exact_log2 (INTVAL (x)) >= 0) - { - fprintf (file, "%d", exact_log2 (INTVAL (x))); - return; - } - abort(); - case 'P': - if (GET_CODE (x) == CONST_INT) - { - fprintf (file, "%d", 31 - (INTVAL (x) & 31)); - return; - } - abort(); - case 'I': - if (GET_CODE (x) == CONST_INT) - fputs ("i", file); - return; - case 'M': - case 'F': - switch (GET_CODE (XEXP (x, 0))) - { - case PRE_DEC: - case PRE_INC: - fputs ("s,mb", file); - break; - case POST_DEC: - case POST_INC: - fputs ("s,ma", file); - break; - case PLUS: - if (GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT - || GET_CODE (XEXP (XEXP (x, 0), 1)) == MULT) - fputs ("x,s", file); - else if (code == 'F') - fputs ("s", file); - break; - default: - if (code == 'F') - fputs ("s", file); - break; - } - return; - case 'G': - output_global_address (file, x, 0); - return; - case 'H': - output_global_address (file, x, 1); - return; - case 0: /* Don't do anything special */ - break; - case 'Z': - { - unsigned op[3]; - compute_zdepi_operands (INTVAL (x), op); - fprintf (file, "%d,%d,%d", op[0], op[1], op[2]); - return; - } - default: - abort (); - } - if (GET_CODE (x) == REG) - { - fputs (reg_names [REGNO (x)], file); - if (FP_REG_P (x) && GET_MODE_SIZE (GET_MODE (x)) <= 4 && (REGNO (x) & 1) == 0) - fputs ("L", file); - } - else if (GET_CODE (x) == MEM) - { - int size = GET_MODE_SIZE (GET_MODE (x)); - rtx base = XEXP (XEXP (x, 0), 0); - switch (GET_CODE (XEXP (x, 0))) - { - case PRE_DEC: - case POST_DEC: - fprintf (file, "-%d(0,%s)", size, reg_names [REGNO (base)]); - break; - case PRE_INC: - case POST_INC: - fprintf (file, "%d(0,%s)", size, reg_names [REGNO (base)]); - break; - default: - if (GET_CODE (XEXP (x, 0)) == PLUS - && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT) - fprintf (file, "%s(0,%s)", - reg_names [REGNO (XEXP (XEXP (XEXP (x, 0), 0), 0))], - reg_names [REGNO (XEXP (XEXP (x, 0), 1))]); - else if (GET_CODE (XEXP (x, 0)) == PLUS - && GET_CODE (XEXP (XEXP (x, 0), 1)) == MULT) - fprintf (file, "%s(0,%s)", - reg_names [REGNO (XEXP (XEXP (XEXP (x, 0), 1), 0))], - reg_names [REGNO (XEXP (XEXP (x, 0), 0))]); - else - output_address (XEXP (x, 0)); - break; - } - } - else - output_addr_const (file, x); -} - -/* output a SYMBOL_REF or a CONST expression involving a SYMBOL_REF. */ - -void -output_global_address (file, x, round_constant) - FILE *file; - rtx x; - int round_constant; -{ - - /* Imagine (high (const (plus ...))). */ - if (GET_CODE (x) == HIGH) - x = XEXP (x, 0); - - if (GET_CODE (x) == SYMBOL_REF && read_only_operand (x)) - assemble_name (file, XSTR (x, 0)); - else if (GET_CODE (x) == SYMBOL_REF && !flag_pic) - { - assemble_name (file, XSTR (x, 0)); - fputs ("-$global$", file); - } - else if (GET_CODE (x) == CONST) - { - char *sep = ""; - int offset = 0; /* assembler wants -$global$ at end */ - rtx base = NULL_RTX; - - if (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF) - { - base = XEXP (XEXP (x, 0), 0); - output_addr_const (file, base); - } - else if (GET_CODE (XEXP (XEXP (x, 0), 0)) == CONST_INT) - offset = INTVAL (XEXP (XEXP (x, 0), 0)); - else abort (); - - if (GET_CODE (XEXP (XEXP (x, 0), 1)) == SYMBOL_REF) - { - base = XEXP (XEXP (x, 0), 1); - output_addr_const (file, base); - } - else if (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT) - offset = INTVAL (XEXP (XEXP (x, 0),1)); - else abort (); - - /* How bogus. The compiler is apparently responsible for - rounding the constant if it uses an LR field selector. - - The linker and/or assembler seem a better place since - they have to do this kind of thing already. - - If we fail to do this, HP's optimizing linker may eliminate - an addil, but not update the ldw/stw/ldo instruction that - uses the result of the addil. */ - if (round_constant) - offset = ((offset + 0x1000) & ~0x1fff); - - if (GET_CODE (XEXP (x, 0)) == PLUS) - { - if (offset < 0) - { - offset = -offset; - sep = "-"; - } - else - sep = "+"; - } - else if (GET_CODE (XEXP (x, 0)) == MINUS - && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)) - sep = "-"; - else abort (); - - if (!read_only_operand (base) && !flag_pic) - fputs ("-$global$", file); - if (offset) - fprintf (file,"%s%d", sep, offset); - } - else - output_addr_const (file, x); -} - -void -output_deferred_plabels (file) - FILE *file; -{ - int i; - /* If we have deferred plabels, then we need to switch into the data - section and align it to a 4 byte boundary before we output the - deferred plabels. */ - if (n_deferred_plabels) - { - data_section (); - ASM_OUTPUT_ALIGN (file, 2); - } - - /* Now output the deferred plabels. */ - for (i = 0; i < n_deferred_plabels; i++) - { - ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (deferred_plabels[i].internal_label)); - assemble_integer (gen_rtx_SYMBOL_REF (VOIDmode, - deferred_plabels[i].name), 4, 1); - } -} - -/* HP's millicode routines mean something special to the assembler. - Keep track of which ones we have used. */ - -enum millicodes { remI, remU, divI, divU, mulI, mulU, end1000 }; -static char imported[(int)end1000]; -static char *milli_names[] = {"remI", "remU", "divI", "divU", "mulI", "mulU"}; -static char import_string[] = ".IMPORT $$....,MILLICODE"; -#define MILLI_START 10 - -static void -import_milli (code) - enum millicodes code; -{ - char str[sizeof (import_string)]; - - if (!imported[(int)code]) - { - imported[(int)code] = 1; - strcpy (str, import_string); - strncpy (str + MILLI_START, milli_names[(int)code], 4); - output_asm_insn (str, 0); - } -} - -/* The register constraints have put the operands and return value in - the proper registers. */ - -char * -output_mul_insn (unsignedp, insn) - int unsignedp ATTRIBUTE_UNUSED; - rtx insn; -{ - import_milli (mulI); - return output_millicode_call (insn, gen_rtx_SYMBOL_REF (SImode, "$$mulI")); -} - -/* Emit the rtl for doing a division by a constant. */ - -/* Do magic division millicodes exist for this value? */ -static int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, - 1, 1}; - -/* We'll use an array to keep track of the magic millicodes and - whether or not we've used them already. [n][0] is signed, [n][1] is - unsigned. */ - -static int div_milli[16][2]; - -int -div_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (mode == SImode - && ((GET_CODE (op) == REG && REGNO (op) == 25) - || (GET_CODE (op) == CONST_INT && INTVAL (op) > 0 - && INTVAL (op) < 16 && magic_milli[INTVAL (op)]))); -} - -int -emit_hpdiv_const (operands, unsignedp) - rtx *operands; - int unsignedp; -{ - if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) > 0 - && INTVAL (operands[2]) < 16 - && magic_milli[INTVAL (operands[2])]) - { - emit_move_insn (gen_rtx_REG (SImode, 26), operands[1]); - emit - (gen_rtx - (PARALLEL, VOIDmode, - gen_rtvec (5, gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, 29), - gen_rtx_fmt_ee (unsignedp ? UDIV : DIV, - SImode, - gen_rtx_REG (SImode, 26), - operands[2])), - gen_rtx_CLOBBER (VOIDmode, operands[3]), - gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 26)), - gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 25)), - gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 31))))); - emit_move_insn (operands[0], gen_rtx_REG (SImode, 29)); - return 1; - } - return 0; -} - -char * -output_div_insn (operands, unsignedp, insn) - rtx *operands; - int unsignedp; - rtx insn; -{ - int divisor; - - /* If the divisor is a constant, try to use one of the special - opcodes .*/ - if (GET_CODE (operands[0]) == CONST_INT) - { - static char buf[100]; - divisor = INTVAL (operands[0]); - if (!div_milli[divisor][unsignedp]) - { - div_milli[divisor][unsignedp] = 1; - if (unsignedp) - output_asm_insn (".IMPORT $$divU_%0,MILLICODE", operands); - else - output_asm_insn (".IMPORT $$divI_%0,MILLICODE", operands); - } - if (unsignedp) - { - sprintf (buf, "$$divU_%d", INTVAL (operands[0])); - return output_millicode_call (insn, - gen_rtx_SYMBOL_REF (SImode, buf)); - } - else - { - sprintf (buf, "$$divI_%d", INTVAL (operands[0])); - return output_millicode_call (insn, - gen_rtx_SYMBOL_REF (SImode, buf)); - } - } - /* Divisor isn't a special constant. */ - else - { - if (unsignedp) - { - import_milli (divU); - return output_millicode_call (insn, - gen_rtx_SYMBOL_REF (SImode, "$$divU")); - } - else - { - import_milli (divI); - return output_millicode_call (insn, - gen_rtx_SYMBOL_REF (SImode, "$$divI")); - } - } -} - -/* Output a $$rem millicode to do mod. */ - -char * -output_mod_insn (unsignedp, insn) - int unsignedp; - rtx insn; -{ - if (unsignedp) - { - import_milli (remU); - return output_millicode_call (insn, - gen_rtx_SYMBOL_REF (SImode, "$$remU")); - } - else - { - import_milli (remI); - return output_millicode_call (insn, - gen_rtx_SYMBOL_REF (SImode, "$$remI")); - } -} - -void -output_arg_descriptor (call_insn) - rtx call_insn; -{ - char *arg_regs[4]; - enum machine_mode arg_mode; - rtx link; - int i, output_flag = 0; - int regno; - - for (i = 0; i < 4; i++) - arg_regs[i] = 0; - - /* Specify explicitly that no argument relocations should take place - if using the portable runtime calling conventions. */ - if (TARGET_PORTABLE_RUNTIME) - { - fputs ("\t.CALL ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO,RETVAL=NO\n", - asm_out_file); - return; - } - - if (GET_CODE (call_insn) != CALL_INSN) - abort (); - for (link = CALL_INSN_FUNCTION_USAGE (call_insn); link; link = XEXP (link, 1)) - { - rtx use = XEXP (link, 0); - - if (! (GET_CODE (use) == USE - && GET_CODE (XEXP (use, 0)) == REG - && FUNCTION_ARG_REGNO_P (REGNO (XEXP (use, 0))))) - continue; - - arg_mode = GET_MODE (XEXP (use, 0)); - regno = REGNO (XEXP (use, 0)); - if (regno >= 23 && regno <= 26) - { - arg_regs[26 - regno] = "GR"; - if (arg_mode == DImode) - arg_regs[25 - regno] = "GR"; - } - else if (regno >= 32 && regno <= 39) - { - if (arg_mode == SFmode) - arg_regs[(regno - 32) / 2] = "FR"; - else - { -#ifndef HP_FP_ARG_DESCRIPTOR_REVERSED - arg_regs[(regno - 34) / 2] = "FR"; - arg_regs[(regno - 34) / 2 + 1] = "FU"; -#else - arg_regs[(regno - 34) / 2] = "FU"; - arg_regs[(regno - 34) / 2 + 1] = "FR"; -#endif - } - } - } - fputs ("\t.CALL ", asm_out_file); - for (i = 0; i < 4; i++) - { - if (arg_regs[i]) - { - if (output_flag++) - fputc (',', asm_out_file); - fprintf (asm_out_file, "ARGW%d=%s", i, arg_regs[i]); - } - } - fputc ('\n', asm_out_file); -} - -/* Return the class of any secondary reload register that is needed to - move IN into a register in class CLASS using mode MODE. - - Profiling has showed this routine and its descendants account for - a significant amount of compile time (~7%). So it has been - optimized to reduce redundant computations and eliminate useless - function calls. - - It might be worthwhile to try and make this a leaf function too. */ - -enum reg_class -secondary_reload_class (class, mode, in) - enum reg_class class; - enum machine_mode mode; - rtx in; -{ - int regno, is_symbolic; - - /* Trying to load a constant into a FP register during PIC code - generation will require %r1 as a scratch register. */ - if (flag_pic == 2 - && GET_MODE_CLASS (mode) == MODE_INT - && FP_REG_CLASS_P (class) - && (GET_CODE (in) == CONST_INT || GET_CODE (in) == CONST_DOUBLE)) - return R1_REGS; - - /* Profiling showed the PA port spends about 1.3% of its compilation - time in true_regnum from calls inside secondary_reload_class. */ - - if (GET_CODE (in) == REG) - { - regno = REGNO (in); - if (regno >= FIRST_PSEUDO_REGISTER) - regno = true_regnum (in); - } - else if (GET_CODE (in) == SUBREG) - regno = true_regnum (in); - else - regno = -1; - - /* If we have something like (mem (mem (...)), we can safely assume the - inner MEM will end up in a general register after reloading, so there's - no need for a secondary reload. */ - if (GET_CODE (in) == MEM - && GET_CODE (XEXP (in, 0)) == MEM) - return NO_REGS; - - /* Handle out of range displacement for integer mode loads/stores of - FP registers. */ - if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1) - && GET_MODE_CLASS (mode) == MODE_INT - && FP_REG_CLASS_P (class)) - || (class == SHIFT_REGS && (regno <= 0 || regno >= 32))) - return GENERAL_REGS; - - if (GET_CODE (in) == HIGH) - in = XEXP (in, 0); - - /* Profiling has showed GCC spends about 2.6% of its compilation - time in symbolic_operand from calls inside secondary_reload_class. - - We use an inline copy and only compute its return value once to avoid - useless work. */ - switch (GET_CODE (in)) - { - rtx tmp; - - case SYMBOL_REF: - case LABEL_REF: - is_symbolic = 1; - break; - case CONST: - tmp = XEXP (in, 0); - is_symbolic = ((GET_CODE (XEXP (tmp, 0)) == SYMBOL_REF - || GET_CODE (XEXP (tmp, 0)) == LABEL_REF) - && GET_CODE (XEXP (tmp, 1)) == CONST_INT); - break; - - default: - is_symbolic = 0; - break; - } - - if (!flag_pic - && is_symbolic - && read_only_operand (in)) - return NO_REGS; - - if (class != R1_REGS && is_symbolic) - return R1_REGS; - - return NO_REGS; -} - -enum direction -function_arg_padding (mode, type) - enum machine_mode mode; - tree type; -{ - int size; - - if (mode == BLKmode) - { - if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) - size = int_size_in_bytes (type) * BITS_PER_UNIT; - else - return upward; /* Don't know if this is right, but */ - /* same as old definition. */ - } - else - size = GET_MODE_BITSIZE (mode); - if (size < PARM_BOUNDARY) - return downward; - else if (size % PARM_BOUNDARY) - return upward; - else - return none; -} - - -/* Do what is necessary for `va_start'. The argument is ignored; - We look at the current function to determine if stdargs or varargs - is used and fill in an initial va_list. A pointer to this constructor - is returned. */ - -struct rtx_def * -hppa_builtin_saveregs (arglist) - tree arglist ATTRIBUTE_UNUSED; -{ - rtx offset, dest; - tree fntype = TREE_TYPE (current_function_decl); - int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0 - && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) - != void_type_node))) - ? UNITS_PER_WORD : 0); - - if (argadj) - offset = plus_constant (current_function_arg_offset_rtx, argadj); - else - offset = current_function_arg_offset_rtx; - - /* Store general registers on the stack. */ - dest = gen_rtx_MEM (BLKmode, - plus_constant (current_function_internal_arg_pointer, - -16)); - move_block_from_reg (23, dest, 4, 4 * UNITS_PER_WORD); - - /* move_block_from_reg will emit code to store the argument registers - individually as scalar stores. - - However, other insns may later load from the same addresses for - a structure load (passing a struct to a varargs routine). - - The alias code assumes that such aliasing can never happen, so we - have to keep memory referencing insns from moving up beyond the - last argument register store. So we emit a blockage insn here. */ - emit_insn (gen_blockage ()); - - if (current_function_check_memory_usage) - emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3, - dest, ptr_mode, - GEN_INT (4 * UNITS_PER_WORD), TYPE_MODE (sizetype), - GEN_INT (MEMORY_USE_RW), - TYPE_MODE (integer_type_node)); - - return copy_to_reg (expand_binop (Pmode, add_optab, - current_function_internal_arg_pointer, - offset, 0, 0, OPTAB_LIB_WIDEN)); -} - -/* This routine handles all the normal conditional branch sequences we - might need to generate. It handles compare immediate vs compare - register, nullification of delay slots, varying length branches, - negated branches, and all combinations of the above. It returns the - output appropriate to emit the branch corresponding to all given - parameters. */ - -char * -output_cbranch (operands, nullify, length, negated, insn) - rtx *operands; - int nullify, length, negated; - rtx insn; -{ - static char buf[100]; - int useskip = 0; - - /* A conditional branch to the following instruction (eg the delay slot) is - asking for a disaster. This can happen when not optimizing. - - In such cases it is safe to emit nothing. */ - - if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn)) - return ""; - - /* If this is a long branch with its delay slot unfilled, set `nullify' - as it can nullify the delay slot and save a nop. */ - if (length == 8 && dbr_sequence_length () == 0) - nullify = 1; - - /* If this is a short forward conditional branch which did not get - its delay slot filled, the delay slot can still be nullified. */ - if (! nullify && length == 4 && dbr_sequence_length () == 0) - nullify = forward_branch_p (insn); - - /* A forward branch over a single nullified insn can be done with a - comclr instruction. This avoids a single cycle penalty due to - mis-predicted branch if we fall through (branch not taken). */ - if (length == 4 - && next_real_insn (insn) != 0 - && get_attr_length (next_real_insn (insn)) == 4 - && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn)) - && nullify) - useskip = 1; - - switch (length) - { - /* All short conditional branches except backwards with an unfilled - delay slot. */ - case 4: - if (useskip) - strcpy (buf, "com%I2clr,"); - else - strcpy (buf, "com%I2b,"); - if (negated) - strcat (buf, "%B3"); - else - strcat (buf, "%S3"); - if (useskip) - strcat (buf, " %2,%r1,0"); - else if (nullify) - strcat (buf, ",n %2,%r1,%0"); - else - strcat (buf, " %2,%r1,%0"); - break; - - /* All long conditionals. Note an short backward branch with an - unfilled delay slot is treated just like a long backward branch - with an unfilled delay slot. */ - case 8: - /* Handle weird backwards branch with a filled delay slot - with is nullified. */ - if (dbr_sequence_length () != 0 - && ! forward_branch_p (insn) - && nullify) - { - strcpy (buf, "com%I2b,"); - if (negated) - strcat (buf, "%S3"); - else - strcat (buf, "%B3"); - strcat (buf, ",n %2,%r1,.+12\n\tbl %0,0"); - } - /* Handle short backwards branch with an unfilled delay slot. - Using a comb;nop rather than comiclr;bl saves 1 cycle for both - taken and untaken branches. */ - else if (dbr_sequence_length () == 0 - && ! forward_branch_p (insn) - && insn_addresses - && VAL_14_BITS_P (insn_addresses[INSN_UID (JUMP_LABEL (insn))] - - insn_addresses[INSN_UID (insn)] - 8)) - { - strcpy (buf, "com%I2b,"); - if (negated) - strcat (buf, "%B3 %2,%r1,%0%#"); - else - strcat (buf, "%S3 %2,%r1,%0%#"); - } - else - { - strcpy (buf, "com%I2clr,"); - if (negated) - strcat (buf, "%S3"); - else - strcat (buf, "%B3"); - if (nullify) - strcat (buf, " %2,%r1,0\n\tbl,n %0,0"); - else - strcat (buf, " %2,%r1,0\n\tbl %0,0"); - } - break; - - case 20: - /* Very long branch. Right now we only handle these when not - optimizing. See "jump" pattern in pa.md for details. */ - if (optimize) - abort (); - - /* Create a reversed conditional branch which branches around - the following insns. */ - if (negated) - strcpy (buf, "com%I2b,%S3,n %2,%r1,.+20"); - else - strcpy (buf, "com%I2b,%B3,n %2,%r1,.+20"); - output_asm_insn (buf, operands); - - /* Output an insn to save %r1. */ - output_asm_insn ("stw %%r1,-16(%%r30)", operands); - - /* Now output a very long branch to the original target. */ - output_asm_insn ("ldil L'%l0,%%r1\n\tbe R'%l0(%%sr4,%%r1)", operands); - - /* Now restore the value of %r1 in the delay slot. We're not - optimizing so we know nothing else can be in the delay slot. */ - return "ldw -16(%%r30),%%r1"; - - case 28: - /* Very long branch when generating PIC code. Right now we only - handle these when not optimizing. See "jump" pattern in pa.md - for details. */ - if (optimize) - abort (); - - /* Create a reversed conditional branch which branches around - the following insns. */ - if (negated) - strcpy (buf, "com%I2b,%S3,n %2,%r1,.+28"); - else - strcpy (buf, "com%I2b,%B3,n %2,%r1,.+28"); - output_asm_insn (buf, operands); - - /* Output an insn to save %r1. */ - output_asm_insn ("stw %%r1,-16(%%r30)", operands); - - /* Now output a very long PIC branch to the original target. */ - { - rtx xoperands[5]; - - xoperands[0] = operands[0]; - xoperands[1] = operands[1]; - xoperands[2] = operands[2]; - xoperands[3] = operands[3]; - xoperands[4] = gen_label_rtx (); - - output_asm_insn ("bl .+8,%%r1\n\taddil L'%l0-%l4,%%r1", xoperands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", - CODE_LABEL_NUMBER (xoperands[4])); - output_asm_insn ("ldo R'%l0-%l4(%%r1),%%r1\n\tbv 0(%%r1)", xoperands); - } - - /* Now restore the value of %r1 in the delay slot. We're not - optimizing so we know nothing else can be in the delay slot. */ - return "ldw -16(%%r30),%%r1"; - - default: - abort(); - } - return buf; -} - -/* This routine handles all the branch-on-bit conditional branch sequences we - might need to generate. It handles nullification of delay slots, - varying length branches, negated branches and all combinations of the - above. it returns the appropriate output template to emit the branch. */ - -char * -output_bb (operands, nullify, length, negated, insn, which) - rtx *operands ATTRIBUTE_UNUSED; - int nullify, length, negated; - rtx insn; - int which; -{ - static char buf[100]; - int useskip = 0; - - /* A conditional branch to the following instruction (eg the delay slot) is - asking for a disaster. I do not think this can happen as this pattern - is only used when optimizing; jump optimization should eliminate the - jump. But be prepared just in case. */ - - if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn)) - return ""; - - /* If this is a long branch with its delay slot unfilled, set `nullify' - as it can nullify the delay slot and save a nop. */ - if (length == 8 && dbr_sequence_length () == 0) - nullify = 1; - - /* If this is a short forward conditional branch which did not get - its delay slot filled, the delay slot can still be nullified. */ - if (! nullify && length == 4 && dbr_sequence_length () == 0) - nullify = forward_branch_p (insn); - - /* A forward branch over a single nullified insn can be done with a - extrs instruction. This avoids a single cycle penalty due to - mis-predicted branch if we fall through (branch not taken). */ - - if (length == 4 - && next_real_insn (insn) != 0 - && get_attr_length (next_real_insn (insn)) == 4 - && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn)) - && nullify) - useskip = 1; - - switch (length) - { - - /* All short conditional branches except backwards with an unfilled - delay slot. */ - case 4: - if (useskip) - strcpy (buf, "extrs,"); - else - strcpy (buf, "bb,"); - if ((which == 0 && negated) - || (which == 1 && ! negated)) - strcat (buf, ">="); - else - strcat (buf, "<"); - if (useskip) - strcat (buf, " %0,%1,1,0"); - else if (nullify && negated) - strcat (buf, ",n %0,%1,%3"); - else if (nullify && ! negated) - strcat (buf, ",n %0,%1,%2"); - else if (! nullify && negated) - strcat (buf, "%0,%1,%3"); - else if (! nullify && ! negated) - strcat (buf, " %0,%1,%2"); - break; - - /* All long conditionals. Note an short backward branch with an - unfilled delay slot is treated just like a long backward branch - with an unfilled delay slot. */ - case 8: - /* Handle weird backwards branch with a filled delay slot - with is nullified. */ - if (dbr_sequence_length () != 0 - && ! forward_branch_p (insn) - && nullify) - { - strcpy (buf, "bb,"); - if ((which == 0 && negated) - || (which == 1 && ! negated)) - strcat (buf, "<"); - else - strcat (buf, ">="); - if (negated) - strcat (buf, ",n %0,%1,.+12\n\tbl %3,0"); - else - strcat (buf, ",n %0,%1,.+12\n\tbl %2,0"); - } - /* Handle short backwards branch with an unfilled delay slot. - Using a bb;nop rather than extrs;bl saves 1 cycle for both - taken and untaken branches. */ - else if (dbr_sequence_length () == 0 - && ! forward_branch_p (insn) - && insn_addresses - && VAL_14_BITS_P (insn_addresses[INSN_UID (JUMP_LABEL (insn))] - - insn_addresses[INSN_UID (insn)] - 8)) - { - strcpy (buf, "bb,"); - if ((which == 0 && negated) - || (which == 1 && ! negated)) - strcat (buf, ">="); - else - strcat (buf, "<"); - if (negated) - strcat (buf, " %0,%1,%3%#"); - else - strcat (buf, " %0,%1,%2%#"); - } - else - { - strcpy (buf, "extrs,"); - if ((which == 0 && negated) - || (which == 1 && ! negated)) - strcat (buf, "<"); - else - strcat (buf, ">="); - if (nullify && negated) - strcat (buf, " %0,%1,1,0\n\tbl,n %3,0"); - else if (nullify && ! negated) - strcat (buf, " %0,%1,1,0\n\tbl,n %2,0"); - else if (negated) - strcat (buf, " %0,%1,1,0\n\tbl %3,0"); - else - strcat (buf, " %0,%1,1,0\n\tbl %2,0"); - } - break; - - default: - abort(); - } - return buf; -} - -/* This routine handles all the branch-on-variable-bit conditional branch - sequences we might need to generate. It handles nullification of delay - slots, varying length branches, negated branches and all combinations - of the above. it returns the appropriate output template to emit the - branch. */ - -char * -output_bvb (operands, nullify, length, negated, insn, which) - rtx *operands ATTRIBUTE_UNUSED; - int nullify, length, negated; - rtx insn; - int which; -{ - static char buf[100]; - int useskip = 0; - - /* A conditional branch to the following instruction (eg the delay slot) is - asking for a disaster. I do not think this can happen as this pattern - is only used when optimizing; jump optimization should eliminate the - jump. But be prepared just in case. */ - - if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn)) - return ""; - - /* If this is a long branch with its delay slot unfilled, set `nullify' - as it can nullify the delay slot and save a nop. */ - if (length == 8 && dbr_sequence_length () == 0) - nullify = 1; - - /* If this is a short forward conditional branch which did not get - its delay slot filled, the delay slot can still be nullified. */ - if (! nullify && length == 4 && dbr_sequence_length () == 0) - nullify = forward_branch_p (insn); - - /* A forward branch over a single nullified insn can be done with a - extrs instruction. This avoids a single cycle penalty due to - mis-predicted branch if we fall through (branch not taken). */ - - if (length == 4 - && next_real_insn (insn) != 0 - && get_attr_length (next_real_insn (insn)) == 4 - && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn)) - && nullify) - useskip = 1; - - switch (length) - { - - /* All short conditional branches except backwards with an unfilled - delay slot. */ - case 4: - if (useskip) - strcpy (buf, "vextrs,"); - else - strcpy (buf, "bvb,"); - if ((which == 0 && negated) - || (which == 1 && ! negated)) - strcat (buf, ">="); - else - strcat (buf, "<"); - if (useskip) - strcat (buf, " %0,1,0"); - else if (nullify && negated) - strcat (buf, ",n %0,%3"); - else if (nullify && ! negated) - strcat (buf, ",n %0,%2"); - else if (! nullify && negated) - strcat (buf, "%0,%3"); - else if (! nullify && ! negated) - strcat (buf, " %0,%2"); - break; - - /* All long conditionals. Note an short backward branch with an - unfilled delay slot is treated just like a long backward branch - with an unfilled delay slot. */ - case 8: - /* Handle weird backwards branch with a filled delay slot - with is nullified. */ - if (dbr_sequence_length () != 0 - && ! forward_branch_p (insn) - && nullify) - { - strcpy (buf, "bvb,"); - if ((which == 0 && negated) - || (which == 1 && ! negated)) - strcat (buf, "<"); - else - strcat (buf, ">="); - if (negated) - strcat (buf, ",n %0,.+12\n\tbl %3,0"); - else - strcat (buf, ",n %0,.+12\n\tbl %2,0"); - } - /* Handle short backwards branch with an unfilled delay slot. - Using a bb;nop rather than extrs;bl saves 1 cycle for both - taken and untaken branches. */ - else if (dbr_sequence_length () == 0 - && ! forward_branch_p (insn) - && insn_addresses - && VAL_14_BITS_P (insn_addresses[INSN_UID (JUMP_LABEL (insn))] - - insn_addresses[INSN_UID (insn)] - 8)) - { - strcpy (buf, "bvb,"); - if ((which == 0 && negated) - || (which == 1 && ! negated)) - strcat (buf, ">="); - else - strcat (buf, "<"); - if (negated) - strcat (buf, " %0,%3%#"); - else - strcat (buf, " %0,%2%#"); - } - else - { - strcpy (buf, "vextrs,"); - if ((which == 0 && negated) - || (which == 1 && ! negated)) - strcat (buf, "<"); - else - strcat (buf, ">="); - if (nullify && negated) - strcat (buf, " %0,1,0\n\tbl,n %3,0"); - else if (nullify && ! negated) - strcat (buf, " %0,1,0\n\tbl,n %2,0"); - else if (negated) - strcat (buf, " %0,1,0\n\tbl %3,0"); - else - strcat (buf, " %0,1,0\n\tbl %2,0"); - } - break; - - default: - abort(); - } - return buf; -} - -/* Return the output template for emitting a dbra type insn. - - Note it may perform some output operations on its own before - returning the final output string. */ -char * -output_dbra (operands, insn, which_alternative) - rtx *operands; - rtx insn; - int which_alternative; -{ - - /* A conditional branch to the following instruction (eg the delay slot) is - asking for a disaster. Be prepared! */ - - if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn)) - { - if (which_alternative == 0) - return "ldo %1(%0),%0"; - else if (which_alternative == 1) - { - output_asm_insn ("fstws %0,-16(0,%%r30)",operands); - output_asm_insn ("ldw -16(0,%%r30),%4",operands); - output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(0,%%r30)", operands); - return "fldws -16(0,%%r30),%0"; - } - else - { - output_asm_insn ("ldw %0,%4", operands); - return "ldo %1(%4),%4\n\tstw %4,%0"; - } - } - - if (which_alternative == 0) - { - int nullify = INSN_ANNULLED_BRANCH_P (insn); - int length = get_attr_length (insn); - - /* If this is a long branch with its delay slot unfilled, set `nullify' - as it can nullify the delay slot and save a nop. */ - if (length == 8 && dbr_sequence_length () == 0) - nullify = 1; - - /* If this is a short forward conditional branch which did not get - its delay slot filled, the delay slot can still be nullified. */ - if (! nullify && length == 4 && dbr_sequence_length () == 0) - nullify = forward_branch_p (insn); - - /* Handle short versions first. */ - if (length == 4 && nullify) - return "addib,%C2,n %1,%0,%3"; - else if (length == 4 && ! nullify) - return "addib,%C2 %1,%0,%3"; - else if (length == 8) - { - /* Handle weird backwards branch with a fulled delay slot - which is nullified. */ - if (dbr_sequence_length () != 0 - && ! forward_branch_p (insn) - && nullify) - return "addib,%N2,n %1,%0,.+12\n\tbl %3,0"; - /* Handle short backwards branch with an unfilled delay slot. - Using a addb;nop rather than addi;bl saves 1 cycle for both - taken and untaken branches. */ - else if (dbr_sequence_length () == 0 - && ! forward_branch_p (insn) - && insn_addresses - && VAL_14_BITS_P (insn_addresses[INSN_UID (JUMP_LABEL (insn))] - - insn_addresses[INSN_UID (insn)] - 8)) - return "addib,%C2 %1,%0,%3%#"; - - /* Handle normal cases. */ - if (nullify) - return "addi,%N2 %1,%0,%0\n\tbl,n %3,0"; - else - return "addi,%N2 %1,%0,%0\n\tbl %3,0"; - } - else - abort(); - } - /* Deal with gross reload from FP register case. */ - else if (which_alternative == 1) - { - /* Move loop counter from FP register to MEM then into a GR, - increment the GR, store the GR into MEM, and finally reload - the FP register from MEM from within the branch's delay slot. */ - output_asm_insn ("fstws %0,-16(0,%%r30)\n\tldw -16(0,%%r30),%4",operands); - output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(0,%%r30)", operands); - if (get_attr_length (insn) == 24) - return "comb,%S2 0,%4,%3\n\tfldws -16(0,%%r30),%0"; - else - return "comclr,%B2 0,%4,0\n\tbl %3,0\n\tfldws -16(0,%%r30),%0"; - } - /* Deal with gross reload from memory case. */ - else - { - /* Reload loop counter from memory, the store back to memory - happens in the branch's delay slot. */ - output_asm_insn ("ldw %0,%4", operands); - if (get_attr_length (insn) == 12) - return "addib,%C2 %1,%4,%3\n\tstw %4,%0"; - else - return "addi,%N2 %1,%4,%4\n\tbl %3,0\n\tstw %4,%0"; - } -} - -/* Return the output template for emitting a dbra type insn. - - Note it may perform some output operations on its own before - returning the final output string. */ -char * -output_movb (operands, insn, which_alternative, reverse_comparison) - rtx *operands; - rtx insn; - int which_alternative; - int reverse_comparison; -{ - - /* A conditional branch to the following instruction (eg the delay slot) is - asking for a disaster. Be prepared! */ - - if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn)) - { - if (which_alternative == 0) - return "copy %1,%0"; - else if (which_alternative == 1) - { - output_asm_insn ("stw %1,-16(0,%%r30)",operands); - return "fldws -16(0,%%r30),%0"; - } - else if (which_alternative == 2) - return "stw %1,%0"; - else - return "mtsar %r1"; - } - - /* Support the second variant. */ - if (reverse_comparison) - PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2]))); - - if (which_alternative == 0) - { - int nullify = INSN_ANNULLED_BRANCH_P (insn); - int length = get_attr_length (insn); - - /* If this is a long branch with its delay slot unfilled, set `nullify' - as it can nullify the delay slot and save a nop. */ - if (length == 8 && dbr_sequence_length () == 0) - nullify = 1; - - /* If this is a short forward conditional branch which did not get - its delay slot filled, the delay slot can still be nullified. */ - if (! nullify && length == 4 && dbr_sequence_length () == 0) - nullify = forward_branch_p (insn); - - /* Handle short versions first. */ - if (length == 4 && nullify) - return "movb,%C2,n %1,%0,%3"; - else if (length == 4 && ! nullify) - return "movb,%C2 %1,%0,%3"; - else if (length == 8) - { - /* Handle weird backwards branch with a filled delay slot - which is nullified. */ - if (dbr_sequence_length () != 0 - && ! forward_branch_p (insn) - && nullify) - return "movb,%N2,n %1,%0,.+12\n\tbl %3,0"; - - /* Handle short backwards branch with an unfilled delay slot. - Using a movb;nop rather than or;bl saves 1 cycle for both - taken and untaken branches. */ - else if (dbr_sequence_length () == 0 - && ! forward_branch_p (insn) - && insn_addresses - && VAL_14_BITS_P (insn_addresses[INSN_UID (JUMP_LABEL (insn))] - - insn_addresses[INSN_UID (insn)] - 8)) - return "movb,%C2 %1,%0,%3%#"; - /* Handle normal cases. */ - if (nullify) - return "or,%N2 %1,%%r0,%0\n\tbl,n %3,0"; - else - return "or,%N2 %1,%%r0,%0\n\tbl %3,0"; - } - else - abort(); - } - /* Deal with gross reload from FP register case. */ - else if (which_alternative == 1) - { - /* Move loop counter from FP register to MEM then into a GR, - increment the GR, store the GR into MEM, and finally reload - the FP register from MEM from within the branch's delay slot. */ - output_asm_insn ("stw %1,-16(0,%%r30)",operands); - if (get_attr_length (insn) == 12) - return "comb,%S2 0,%1,%3\n\tfldws -16(0,%%r30),%0"; - else - return "comclr,%B2 0,%1,0\n\tbl %3,0\n\tfldws -16(0,%%r30),%0"; - } - /* Deal with gross reload from memory case. */ - else if (which_alternative == 2) - { - /* Reload loop counter from memory, the store back to memory - happens in the branch's delay slot. */ - if (get_attr_length (insn) == 8) - return "comb,%S2 0,%1,%3\n\tstw %1,%0"; - else - return "comclr,%B2 0,%1,0\n\tbl %3,0\n\tstw %1,%0"; - } - /* Handle SAR as a destination. */ - else - { - if (get_attr_length (insn) == 8) - return "comb,%S2 0,%1,%3\n\tmtsar %r1"; - else - return "comclr,%B2 0,%1,0\n\tbl %3,0\n\tmtsar %r1"; - } -} - - -/* INSN is a millicode call. It may have an unconditional jump in its delay - slot. - - CALL_DEST is the routine we are calling. */ - -char * -output_millicode_call (insn, call_dest) - rtx insn; - rtx call_dest; -{ - int distance; - rtx xoperands[4]; - rtx seq_insn; - - /* Handle common case -- empty delay slot or no jump in the delay slot, - and we're sure that the branch will reach the beginning of the $CODE$ - subspace. */ - if ((dbr_sequence_length () == 0 - && (get_attr_length (insn) == 8 || get_attr_length (insn) == 28)) - || (dbr_sequence_length () != 0 - && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN - && get_attr_length (insn) == 4)) - { - xoperands[0] = call_dest; - output_asm_insn ("bl %0,%%r31%#", xoperands); - return ""; - } - - /* This call may not reach the beginning of the $CODE$ subspace. */ - if (get_attr_length (insn) > 4) - { - int delay_insn_deleted = 0; - rtx xoperands[2]; - - /* We need to emit an inline long-call branch. */ - if (dbr_sequence_length () != 0 - && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN) - { - /* A non-jump insn in the delay slot. By definition we can - emit this insn before the call. */ - final_scan_insn (NEXT_INSN (insn), asm_out_file, optimize, 0, 0); - - /* Now delete the delay insn. */ - PUT_CODE (NEXT_INSN (insn), NOTE); - NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0; - delay_insn_deleted = 1; - } - - /* If we're allowed to use be/ble instructions, then this is the - best sequence to use for a long millicode call. */ - if (TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS - || ! (flag_pic || TARGET_PORTABLE_RUNTIME)) - { - xoperands[0] = call_dest; - output_asm_insn ("ldil L%%%0,%%r31", xoperands); - output_asm_insn ("ble R%%%0(%%sr4,%%r31)", xoperands); - output_asm_insn ("nop", xoperands); - } - /* Pure portable runtime doesn't allow be/ble; we also don't have - PIC support int he assembler/linker, so this sequence is needed. */ - else if (TARGET_PORTABLE_RUNTIME) - { - xoperands[0] = call_dest; - /* Get the address of our target into %r29. */ - output_asm_insn ("ldil L%%%0,%%r29", xoperands); - output_asm_insn ("ldo R%%%0(%%r29),%%r29", xoperands); - - /* Get our return address into %r31. */ - output_asm_insn ("blr 0,%%r31", xoperands); - - /* Jump to our target address in %r29. */ - output_asm_insn ("bv,n 0(%%r29)", xoperands); - - /* Empty delay slot. Note this insn gets fetched twice and - executed once. To be safe we use a nop. */ - output_asm_insn ("nop", xoperands); - return ""; - } - /* PIC long millicode call sequence. */ - else - { - xoperands[0] = call_dest; - xoperands[1] = gen_label_rtx (); - /* Get our address + 8 into %r1. */ - output_asm_insn ("bl .+8,%%r1", xoperands); - - /* Add %r1 to the offset of our target from the next insn. */ - output_asm_insn ("addil L%%%0-%1,%%r1", xoperands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", - CODE_LABEL_NUMBER (xoperands[1])); - output_asm_insn ("ldo R%%%0-%1(%%r1),%%r1", xoperands); - - /* Get the return address into %r31. */ - output_asm_insn ("blr 0,%%r31", xoperands); - - /* Branch to our target which is in %r1. */ - output_asm_insn ("bv,n 0(%%r1)", xoperands); - - /* Empty delay slot. Note this insn gets fetched twice and - executed once. To be safe we use a nop. */ - output_asm_insn ("nop", xoperands); - } - - /* If we had a jump in the call's delay slot, output it now. */ - if (dbr_sequence_length () != 0 - && !delay_insn_deleted) - { - xoperands[0] = XEXP (PATTERN (NEXT_INSN (insn)), 1); - output_asm_insn ("b,n %0", xoperands); - - /* Now delete the delay insn. */ - PUT_CODE (NEXT_INSN (insn), NOTE); - NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0; - } - return ""; - } - - /* This call has an unconditional jump in its delay slot and the - call is known to reach its target or the beginning of the current - subspace. */ - - /* Use the containing sequence insn's address. */ - seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0))); - - distance = insn_addresses[INSN_UID (JUMP_LABEL (NEXT_INSN (insn)))] - - insn_addresses[INSN_UID (seq_insn)] - 8; - - /* If the branch was too far away, emit a normal call followed - by a nop, followed by the unconditional branch. - - If the branch is close, then adjust %r2 from within the - call's delay slot. */ - - xoperands[0] = call_dest; - xoperands[1] = XEXP (PATTERN (NEXT_INSN (insn)), 1); - if (! VAL_14_BITS_P (distance)) - output_asm_insn ("bl %0,%%r31\n\tnop\n\tbl,n %1,%%r0", xoperands); - else - { - xoperands[3] = gen_label_rtx (); - output_asm_insn ("\n\tbl %0,%%r31\n\tldo %1-%3(%%r31),%%r31", xoperands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", - CODE_LABEL_NUMBER (xoperands[3])); - } - - /* Delete the jump. */ - PUT_CODE (NEXT_INSN (insn), NOTE); - NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0; - return ""; -} - -extern struct obstack permanent_obstack; -extern struct obstack *saveable_obstack; -extern struct obstack *rtl_obstack; -extern struct obstack *current_obstack; - -/* INSN is either a function call. It may have an unconditional jump - in its delay slot. - - CALL_DEST is the routine we are calling. */ - -char * -output_call (insn, call_dest) - rtx insn; - rtx call_dest; -{ - int distance; - rtx xoperands[4]; - rtx seq_insn; - - /* Handle common case -- empty delay slot or no jump in the delay slot, - and we're sure that the branch will reach the beginning of the $CODE$ - subspace. */ - if ((dbr_sequence_length () == 0 - && get_attr_length (insn) == 8) - || (dbr_sequence_length () != 0 - && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN - && get_attr_length (insn) == 4)) - { - xoperands[0] = call_dest; - output_asm_insn ("bl %0,%%r2%#", xoperands); - return ""; - } - - /* This call may not reach the beginning of the $CODE$ subspace. */ - if (get_attr_length (insn) > 8) - { - int delay_insn_deleted = 0; - rtx xoperands[2]; - rtx link; - - /* We need to emit an inline long-call branch. Furthermore, - because we're changing a named function call into an indirect - function call well after the parameters have been set up, we - need to make sure any FP args appear in both the integer - and FP registers. Also, we need move any delay slot insn - out of the delay slot. And finally, we can't rely on the linker - being able to fix the call to $$dyncall! -- Yuk!. */ - if (dbr_sequence_length () != 0 - && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN) - { - /* A non-jump insn in the delay slot. By definition we can - emit this insn before the call (and in fact before argument - relocating. */ - final_scan_insn (NEXT_INSN (insn), asm_out_file, optimize, 0, 0); - - /* Now delete the delay insn. */ - PUT_CODE (NEXT_INSN (insn), NOTE); - NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0; - delay_insn_deleted = 1; - } - - /* Now copy any FP arguments into integer registers. */ - for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1)) - { - int arg_mode, regno; - rtx use = XEXP (link, 0); - if (! (GET_CODE (use) == USE - && GET_CODE (XEXP (use, 0)) == REG - && FUNCTION_ARG_REGNO_P (REGNO (XEXP (use, 0))))) - continue; - - arg_mode = GET_MODE (XEXP (use, 0)); - regno = REGNO (XEXP (use, 0)); - /* Is it a floating point register? */ - if (regno >= 32 && regno <= 39) - { - /* Copy from the FP register into an integer register - (via memory). */ - if (arg_mode == SFmode) - { - xoperands[0] = XEXP (use, 0); - xoperands[1] = gen_rtx_REG (SImode, 26 - (regno - 32) / 2); - output_asm_insn ("fstws %0,-16(%%sr0,%%r30)", xoperands); - output_asm_insn ("ldw -16(%%sr0,%%r30),%1", xoperands); - } - else - { - xoperands[0] = XEXP (use, 0); - xoperands[1] = gen_rtx_REG (DImode, 25 - (regno - 34) / 2); - output_asm_insn ("fstds %0,-16(%%sr0,%%r30)", xoperands); - output_asm_insn ("ldw -12(%%sr0,%%r30),%R1", xoperands); - output_asm_insn ("ldw -16(%%sr0,%%r30),%1", xoperands); - } - } - } - - /* Don't have to worry about TARGET_PORTABLE_RUNTIME here since - we don't have any direct calls in that case. */ - { - int i; - char *name = XSTR (call_dest, 0); - - /* See if we have already put this function on the list - of deferred plabels. This list is generally small, - so a liner search is not too ugly. If it proves too - slow replace it with something faster. */ - for (i = 0; i < n_deferred_plabels; i++) - if (strcmp (name, deferred_plabels[i].name) == 0) - break; - - /* If the deferred plabel list is empty, or this entry was - not found on the list, create a new entry on the list. */ - if (deferred_plabels == NULL || i == n_deferred_plabels) - { - struct obstack *ambient_obstack = current_obstack; - struct obstack *ambient_rtl_obstack = rtl_obstack; - char *real_name; - - /* Any RTL we create here needs to live until the end of - the compilation unit and therefore must live on the - permanent obstack. */ - current_obstack = &permanent_obstack; - rtl_obstack = &permanent_obstack; - - if (deferred_plabels == 0) - deferred_plabels = (struct deferred_plabel *) - xmalloc (1 * sizeof (struct deferred_plabel)); - else - deferred_plabels = (struct deferred_plabel *) - xrealloc (deferred_plabels, - ((n_deferred_plabels + 1) - * sizeof (struct deferred_plabel))); - - i = n_deferred_plabels++; - deferred_plabels[i].internal_label = gen_label_rtx (); - deferred_plabels[i].name = obstack_alloc (&permanent_obstack, - strlen (name) + 1); - strcpy (deferred_plabels[i].name, name); - - /* Switch back to normal obstack allocation. */ - current_obstack = ambient_obstack; - rtl_obstack = ambient_rtl_obstack; - - /* Gross. We have just implicitly taken the address of this - function, mark it as such. */ - STRIP_NAME_ENCODING (real_name, name); - TREE_SYMBOL_REFERENCED (get_identifier (real_name)) = 1; - } - - /* We have to load the address of the function using a procedure - label (plabel). Inline plabels can lose for PIC and other - cases, so avoid them by creating a 32bit plabel in the data - segment. */ - if (flag_pic) - { - xoperands[0] = deferred_plabels[i].internal_label; - xoperands[1] = gen_label_rtx (); - - output_asm_insn ("addil LT%%%0,%%r19", xoperands); - output_asm_insn ("ldw RT%%%0(%%r1),%%r22", xoperands); - output_asm_insn ("ldw 0(0,%%r22),%%r22", xoperands); - - /* Get our address + 8 into %r1. */ - output_asm_insn ("bl .+8,%%r1", xoperands); - - /* Add %r1 to the offset of dyncall from the next insn. */ - output_asm_insn ("addil L%%$$dyncall-%1,%%r1", xoperands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", - CODE_LABEL_NUMBER (xoperands[1])); - output_asm_insn ("ldo R%%$$dyncall-%1(%%r1),%%r1", xoperands); - - /* Get the return address into %r31. */ - output_asm_insn ("blr 0,%%r31", xoperands); - - /* Branch to our target which is in %r1. */ - output_asm_insn ("bv 0(%%r1)", xoperands); - - /* Copy the return address into %r2 also. */ - output_asm_insn ("copy %%r31,%%r2", xoperands); - } - else - { - xoperands[0] = deferred_plabels[i].internal_label; - - /* Get the address of our target into %r22. */ - output_asm_insn ("addil LR%%%0-$global$,%%r27", xoperands); - output_asm_insn ("ldw RR%%%0-$global$(%%r1),%%r22", xoperands); - - /* Get the high part of the address of $dyncall into %r2, then - add in the low part in the branch instruction. */ - output_asm_insn ("ldil L%%$$dyncall,%%r2", xoperands); - output_asm_insn ("ble R%%$$dyncall(%%sr4,%%r2)", xoperands); - - /* Copy the return pointer into both %r31 and %r2. */ - output_asm_insn ("copy %%r31,%%r2", xoperands); - } - } - - /* If we had a jump in the call's delay slot, output it now. */ - if (dbr_sequence_length () != 0 - && !delay_insn_deleted) - { - xoperands[0] = XEXP (PATTERN (NEXT_INSN (insn)), 1); - output_asm_insn ("b,n %0", xoperands); - - /* Now delete the delay insn. */ - PUT_CODE (NEXT_INSN (insn), NOTE); - NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0; - } - return ""; - } - - /* This call has an unconditional jump in its delay slot and the - call is known to reach its target or the beginning of the current - subspace. */ - - /* Use the containing sequence insn's address. */ - seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0))); - - distance = insn_addresses[INSN_UID (JUMP_LABEL (NEXT_INSN (insn)))] - - insn_addresses[INSN_UID (seq_insn)] - 8; - - /* If the branch was too far away, emit a normal call followed - by a nop, followed by the unconditional branch. - - If the branch is close, then adjust %r2 from within the - call's delay slot. */ - - xoperands[0] = call_dest; - xoperands[1] = XEXP (PATTERN (NEXT_INSN (insn)), 1); - if (! VAL_14_BITS_P (distance)) - output_asm_insn ("bl %0,%%r2\n\tnop\n\tbl,n %1,%%r0", xoperands); - else - { - xoperands[3] = gen_label_rtx (); - output_asm_insn ("\n\tbl %0,%%r2\n\tldo %1-%3(%%r2),%%r2", xoperands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", - CODE_LABEL_NUMBER (xoperands[3])); - } - - /* Delete the jump. */ - PUT_CODE (NEXT_INSN (insn), NOTE); - NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0; - return ""; -} - -/* In HPUX 8.0's shared library scheme, special relocations are needed - for function labels if they might be passed to a function - in a shared library (because shared libraries don't live in code - space), and special magic is needed to construct their address. - - For reasons too disgusting to describe storage for the new name - is allocated either on the saveable_obstack (released at function - exit) or on the permanent_obstack for things that can never change - (libcall names for example). */ - -void -hppa_encode_label (sym, permanent) - rtx sym; - int permanent; -{ - char *str = XSTR (sym, 0); - int len = strlen (str); - char *newstr; - - newstr = obstack_alloc ((permanent ? &permanent_obstack : saveable_obstack), - len + 2); - - if (str[0] == '*') - *newstr++ = *str++; - strcpy (newstr + 1, str); - *newstr = '@'; - XSTR (sym,0) = newstr; -} - -int -function_label_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return GET_CODE (op) == SYMBOL_REF && FUNCTION_NAME_P (XSTR (op, 0)); -} - -/* Returns 1 if OP is a function label involved in a simple addition - with a constant. Used to keep certain patterns from matching - during instruction combination. */ -int -is_function_label_plus_const (op) - rtx op; -{ - /* Strip off any CONST. */ - if (GET_CODE (op) == CONST) - op = XEXP (op, 0); - - return (GET_CODE (op) == PLUS - && function_label_operand (XEXP (op, 0), Pmode) - && GET_CODE (XEXP (op, 1)) == CONST_INT); -} - -/* Returns 1 if the 6 operands specified in OPERANDS are suitable for - use in fmpyadd instructions. */ -int -fmpyaddoperands (operands) - rtx *operands; -{ - enum machine_mode mode = GET_MODE (operands[0]); - - /* Must be a floating point mode. */ - if (mode != SFmode && mode != DFmode) - return 0; - - /* All modes must be the same. */ - if (! (mode == GET_MODE (operands[1]) - && mode == GET_MODE (operands[2]) - && mode == GET_MODE (operands[3]) - && mode == GET_MODE (operands[4]) - && mode == GET_MODE (operands[5]))) - return 0; - - /* All operands must be registers. */ - if (! (GET_CODE (operands[1]) == REG - && GET_CODE (operands[2]) == REG - && GET_CODE (operands[3]) == REG - && GET_CODE (operands[4]) == REG - && GET_CODE (operands[5]) == REG)) - return 0; - - /* Only 2 real operands to the addition. One of the input operands must - be the same as the output operand. */ - if (! rtx_equal_p (operands[3], operands[4]) - && ! rtx_equal_p (operands[3], operands[5])) - return 0; - - /* Inout operand of add can not conflict with any operands from multiply. */ - if (rtx_equal_p (operands[3], operands[0]) - || rtx_equal_p (operands[3], operands[1]) - || rtx_equal_p (operands[3], operands[2])) - return 0; - - /* multiply can not feed into addition operands. */ - if (rtx_equal_p (operands[4], operands[0]) - || rtx_equal_p (operands[5], operands[0])) - return 0; - - /* SFmode limits the registers to the upper 32 of the 32bit FP regs. */ - if (mode == SFmode - && (REGNO (operands[0]) < 57 - || REGNO (operands[1]) < 57 - || REGNO (operands[2]) < 57 - || REGNO (operands[3]) < 57 - || REGNO (operands[4]) < 57 - || REGNO (operands[5]) < 57)) - return 0; - - /* Passed. Operands are suitable for fmpyadd. */ - return 1; -} - -/* Returns 1 if the 6 operands specified in OPERANDS are suitable for - use in fmpysub instructions. */ -int -fmpysuboperands (operands) - rtx *operands; -{ - enum machine_mode mode = GET_MODE (operands[0]); - - /* Must be a floating point mode. */ - if (mode != SFmode && mode != DFmode) - return 0; - - /* All modes must be the same. */ - if (! (mode == GET_MODE (operands[1]) - && mode == GET_MODE (operands[2]) - && mode == GET_MODE (operands[3]) - && mode == GET_MODE (operands[4]) - && mode == GET_MODE (operands[5]))) - return 0; - - /* All operands must be registers. */ - if (! (GET_CODE (operands[1]) == REG - && GET_CODE (operands[2]) == REG - && GET_CODE (operands[3]) == REG - && GET_CODE (operands[4]) == REG - && GET_CODE (operands[5]) == REG)) - return 0; - - /* Only 2 real operands to the subtraction. Subtraction is not a commutative - operation, so operands[4] must be the same as operand[3]. */ - if (! rtx_equal_p (operands[3], operands[4])) - return 0; - - /* multiply can not feed into subtraction. */ - if (rtx_equal_p (operands[5], operands[0])) - return 0; - - /* Inout operand of sub can not conflict with any operands from multiply. */ - if (rtx_equal_p (operands[3], operands[0]) - || rtx_equal_p (operands[3], operands[1]) - || rtx_equal_p (operands[3], operands[2])) - return 0; - - /* SFmode limits the registers to the upper 32 of the 32bit FP regs. */ - if (mode == SFmode - && (REGNO (operands[0]) < 57 - || REGNO (operands[1]) < 57 - || REGNO (operands[2]) < 57 - || REGNO (operands[3]) < 57 - || REGNO (operands[4]) < 57 - || REGNO (operands[5]) < 57)) - return 0; - - /* Passed. Operands are suitable for fmpysub. */ - return 1; -} - -int -plus_xor_ior_operator (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == PLUS || GET_CODE (op) == XOR - || GET_CODE (op) == IOR); -} - -/* Return 1 if the given constant is 2, 4, or 8. These are the valid - constants for shadd instructions. */ -static int -shadd_constant_p (val) - int val; -{ - if (val == 2 || val == 4 || val == 8) - return 1; - else - return 0; -} - -/* Return 1 if OP is a CONST_INT with the value 2, 4, or 8. These are - the valid constant for shadd instructions. */ -int -shadd_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == CONST_INT && shadd_constant_p (INTVAL (op))); -} - -/* Return 1 if OP is valid as a base register in a reg + reg address. */ - -int -basereg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - /* cse will create some unscaled indexed addresses, however; it - generally isn't a win on the PA, so avoid creating unscaled - indexed addresses until after cse is finished. */ - if (!cse_not_expected) - return 0; - - /* Once reload has started everything is considered valid. Reload should - only create indexed addresses using the stack/frame pointer, and any - others were checked for validity when created by the combine pass. - - Also allow any register when TARGET_NO_SPACE_REGS is in effect since - we don't have to worry about the braindamaged implicit space register - selection using the basereg only (rather than effective address) - screwing us over. */ - if (TARGET_NO_SPACE_REGS || reload_in_progress || reload_completed) - return (GET_CODE (op) == REG); - - /* Stack is always OK for indexing. */ - if (op == stack_pointer_rtx) - return 1; - - /* While it's always safe to index off the frame pointer, it's not - always profitable, particularly when the frame pointer is being - eliminated. */ - if (! flag_omit_frame_pointer && op == frame_pointer_rtx) - return 1; - - /* The only other valid OPs are pseudo registers with - REGNO_POINTER_FLAG set. */ - if (GET_CODE (op) != REG - || REGNO (op) < FIRST_PSEUDO_REGISTER - || ! register_operand (op, mode)) - return 0; - - return REGNO_POINTER_FLAG (REGNO (op)); -} - -/* Return 1 if this operand is anything other than a hard register. */ - -int -non_hard_reg_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return ! (GET_CODE (op) == REG && REGNO (op) < FIRST_PSEUDO_REGISTER); -} - -/* Return 1 if INSN branches forward. Should be using insn_addresses - to avoid walking through all the insns... */ -static int -forward_branch_p (insn) - rtx insn; -{ - rtx label = JUMP_LABEL (insn); - - while (insn) - { - if (insn == label) - break; - else - insn = NEXT_INSN (insn); - } - - return (insn == label); -} - -/* Return 1 if OP is an equality comparison, else return 0. */ -int -eq_neq_comparison_operator (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == EQ || GET_CODE (op) == NE); -} - -/* Return 1 if OP is an operator suitable for use in a movb instruction. */ -int -movb_comparison_operator (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == EQ || GET_CODE (op) == NE - || GET_CODE (op) == LT || GET_CODE (op) == GE); -} - -/* Return 1 if INSN is in the delay slot of a call instruction. */ -int -jump_in_call_delay (insn) - rtx insn; -{ - - if (GET_CODE (insn) != JUMP_INSN) - return 0; - - if (PREV_INSN (insn) - && PREV_INSN (PREV_INSN (insn)) - && GET_CODE (next_active_insn (PREV_INSN (PREV_INSN (insn)))) == INSN) - { - rtx test_insn = next_active_insn (PREV_INSN (PREV_INSN (insn))); - - return (GET_CODE (PATTERN (test_insn)) == SEQUENCE - && XVECEXP (PATTERN (test_insn), 0, 1) == insn); - - } - else - return 0; -} - -/* Output an unconditional move and branch insn. */ - -char * -output_parallel_movb (operands, length) - rtx *operands; - int length; -{ - /* These are the cases in which we win. */ - if (length == 4) - return "mov%I1b,tr %1,%0,%2"; - - /* None of these cases wins, but they don't lose either. */ - if (dbr_sequence_length () == 0) - { - /* Nothing in the delay slot, fake it by putting the combined - insn (the copy or add) in the delay slot of a bl. */ - if (GET_CODE (operands[1]) == CONST_INT) - return "bl %2,0\n\tldi %1,%0"; - else - return "bl %2,0\n\tcopy %1,%0"; - } - else - { - /* Something in the delay slot, but we've got a long branch. */ - if (GET_CODE (operands[1]) == CONST_INT) - return "ldi %1,%0\n\tbl %2,0"; - else - return "copy %1,%0\n\tbl %2,0"; - } -} - -/* Output an unconditional add and branch insn. */ - -char * -output_parallel_addb (operands, length) - rtx *operands; - int length; -{ - /* To make life easy we want operand0 to be the shared input/output - operand and operand1 to be the readonly operand. */ - if (operands[0] == operands[1]) - operands[1] = operands[2]; - - /* These are the cases in which we win. */ - if (length == 4) - return "add%I1b,tr %1,%0,%3"; - - /* None of these cases win, but they don't lose either. */ - if (dbr_sequence_length () == 0) - { - /* Nothing in the delay slot, fake it by putting the combined - insn (the copy or add) in the delay slot of a bl. */ - return "bl %3,0\n\tadd%I1 %1,%0,%0"; - } - else - { - /* Something in the delay slot, but we've got a long branch. */ - return "add%I1 %1,%0,%0\n\tbl %3,0"; - } -} - -/* Return nonzero if INSN (a jump insn) immediately follows a call to - a named function. This is used to discourage creating parallel movb/addb - insns since a jump which immediately follows a call can execute in the - delay slot of the call. - - It is also used to avoid filling the delay slot of a jump which - immediately follows a call since the jump can usually be eliminated - completely by modifying RP in the delay slot of the call. */ - -int -following_call (insn) - rtx insn; -{ - /* CYGNUS LOCAL PA8000/law */ - /* We do not parallel movb,addb or place jumps into call delay slots when - optimizing for the PA8000. */ - if (pa_cpu != PROCESSOR_8000) - return 0; - /* END CYGNUS LOCAL */ - - /* Find the previous real insn, skipping NOTEs. */ - insn = PREV_INSN (insn); - while (insn && GET_CODE (insn) == NOTE) - insn = PREV_INSN (insn); - - /* Check for CALL_INSNs and millicode calls. */ - if (insn - && ((GET_CODE (insn) == CALL_INSN - && get_attr_type (insn) != TYPE_DYNCALL) - || (GET_CODE (insn) == INSN - && GET_CODE (PATTERN (insn)) != SEQUENCE - && GET_CODE (PATTERN (insn)) != USE - && GET_CODE (PATTERN (insn)) != CLOBBER - && get_attr_type (insn) == TYPE_MILLI))) - return 1; - - return 0; -} - -/* Restore any INSN_CODEs for insns with unscaled indexed addresses since - the INSN_CODE might be clobberd by rerecognition triggered by reorg. */ - -static void -restore_unscaled_index_insn_codes (insns) - rtx insns; -{ - rtx insn; - - for (insn = insns; insn; insn = NEXT_INSN (insn)) - { - if (INSN_UID (insn) < max_unscaled_index_insn_codes_uid - && unscaled_index_insn_codes[INSN_UID (insn)] != -1) - INSN_CODE (insn) = unscaled_index_insn_codes[INSN_UID (insn)]; - } -} - -/* Severe braindamage: - - On the PA, address computations within MEM expressions are not - commutative because of the implicit space register selection - from the base register (instead of the entire effective address). - - Because of this mis-feature we have to know which register in a reg+reg - address is the base and which is the index. - - Before reload, the base can be identified by REGNO_POINTER_FLAG. We use - this to force base + index addresses to match a different insn than - index + base addresses. - - We assume that no pass during or after reload creates new unscaled indexed - addresses, so any unscaled indexed address we find after reload must have - at one time been recognized a base + index or index + base and we accept - any register as a base register. - - This scheme assumes that no pass during/after reload will rerecognize an - insn with an unscaled indexed address. This failed due to a reorg call - to rerecognize certain insns. - - So, we record if an insn uses an unscaled indexed address and which - register is the base (via recording of the INSN_CODE for such insns). - - Just before we output code for the function, we make sure all the insns - using unscaled indexed addresses have the same INSN_CODE as they did - immediately before delay slot scheduling. - - This is extremely gross. Long term, I'd like to be able to look at - REG_POINTER_FLAG to handle these kinds of problems. */ - -static void -record_unscaled_index_insn_codes (insns) - rtx insns; -{ - rtx insn; - - max_unscaled_index_insn_codes_uid = get_max_uid (); - unscaled_index_insn_codes - = (int *)xmalloc (max_unscaled_index_insn_codes_uid * sizeof (int)); - memset (unscaled_index_insn_codes, -1, - max_unscaled_index_insn_codes_uid * sizeof (int)); - - for (insn = insns; insn; insn = NEXT_INSN (insn)) - { - rtx set = single_set (insn); - rtx mem = NULL_RTX; - - /* Ignore anything that isn't a normal SET. */ - if (set == NULL_RTX) - continue; - - /* No insns can have more than one MEM. */ - if (GET_CODE (SET_SRC (set)) == MEM) - mem = SET_SRC (set); - - if (GET_CODE (SET_DEST (set)) == MEM) - mem = SET_DEST (set); - - /* If neither operand is a mem, then there's nothing to do. */ - if (mem == NULL_RTX) - continue; - - if (GET_CODE (XEXP (mem, 0)) != PLUS) - continue; - - /* If both are REGs (or SUBREGs), then record the insn code for - this insn. */ - if (REG_P (XEXP (XEXP (mem, 0), 0)) && REG_P (XEXP (XEXP (mem, 0), 1))) - unscaled_index_insn_codes[INSN_UID (insn)] = INSN_CODE (insn); - } -} - -/* We use this hook to perform a PA specific optimization which is difficult - to do in earlier passes. - - We want the delay slots of branches within jump tables to be filled. - None of the compiler passes at the moment even has the notion that a - PA jump table doesn't contain addresses, but instead contains actual - instructions! - - Because we actually jump into the table, the addresses of each entry - must stay constant in relation to the beginning of the table (which - itself must stay constant relative to the instruction to jump into - it). I don't believe we can guarantee earlier passes of the compiler - will adhere to those rules. - - So, late in the compilation process we find all the jump tables, and - expand them into real code -- eg each entry in the jump table vector - will get an appropriate label followed by a jump to the final target. - - Reorg and the final jump pass can then optimize these branches and - fill their delay slots. We end up with smaller, more efficient code. - - The jump instructions within the table are special; we must be able - to identify them during assembly output (if the jumps don't get filled - we need to emit a nop rather than nullifying the delay slot)). We - identify jumps in switch tables by marking the SET with DImode. - - We also surround the jump table itself with BEGIN_BRTAB and END_BRTAB - insns. This serves two purposes, first it prevents jump.c from - noticing that the last N entries in the table jump to the instruction - immediately after the table and deleting the jumps. Second, those - insns mark where we should emit .begin_brtab and .end_brtab directives - when using GAS (allows for better link time optimizations). */ - -void -pa_reorg (insns) - rtx insns; -{ - rtx insn; - - /* Keep track of which insns have unscaled indexed addresses, and which - register is the base address in such insns. */ - record_unscaled_index_insn_codes (insns); - - remove_useless_addtr_insns (insns, 1); - - /* CYGNUS LOCAL PA8000/law */ - /* These optimizations hurt PA8000 performance. */ - if (pa_cpu != PROCESSOR_8000) - pa_combine_instructions (get_insns ()); - /* END CYGNUS LOCAL */ - - /* This is fairly cheap, so always run it if optimizing. */ - if (optimize > 0 && !TARGET_BIG_SWITCH) - { - /* Find and explode all ADDR_VEC or ADDR_DIFF_VEC insns. */ - insns = get_insns (); - for (insn = insns; insn; insn = NEXT_INSN (insn)) - { - rtx pattern, tmp, location; - unsigned int length, i; - - /* Find an ADDR_VEC or ADDR_DIFF_VEC insn to explode. */ - if (GET_CODE (insn) != JUMP_INSN - || (GET_CODE (PATTERN (insn)) != ADDR_VEC - && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)) - continue; - - /* Emit marker for the beginning of the branch table. */ - emit_insn_before (gen_begin_brtab (), insn); - - pattern = PATTERN (insn); - location = PREV_INSN (insn); - length = XVECLEN (pattern, GET_CODE (pattern) == ADDR_DIFF_VEC); - - for (i = 0; i < length; i++) - { - /* Emit a label before each jump to keep jump.c from - removing this code. */ - tmp = gen_label_rtx (); - LABEL_NUSES (tmp) = 1; - emit_label_after (tmp, location); - location = NEXT_INSN (location); - - if (GET_CODE (pattern) == ADDR_VEC) - { - /* Emit the jump itself. */ - tmp = gen_jump (XEXP (XVECEXP (pattern, 0, i), 0)); - tmp = emit_jump_insn_after (tmp, location); - JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 0, i), 0); - /* It is easy to rely on the branch table markers - during assembly output to trigger the correct code - for a switch table jump with an unfilled delay slot, - - However, that requires state and assumes that we look - at insns in order. - - We can't make such assumptions when computing the length - of instructions. Ugh. We could walk the insn chain to - determine if this instruction is in a branch table, but - that can get rather expensive, particularly during the - branch shortening phase of the compiler. - - So instead we mark this jump as being special. This is - far from ideal and knows that no code after this will - muck around with the mode of the JUMP_INSN itself. */ - PUT_MODE (tmp, SImode); - LABEL_NUSES (JUMP_LABEL (tmp))++; - location = NEXT_INSN (location); - } - else - { - /* Emit the jump itself. */ - tmp = gen_jump (XEXP (XVECEXP (pattern, 1, i), 0)); - tmp = emit_jump_insn_after (tmp, location); - JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 1, i), 0); - /* It is easy to rely on the branch table markers - during assembly output to trigger the correct code - for a switch table jump with an unfilled delay slot, - - However, that requires state and assumes that we look - at insns in order. - - We can't make such assumptions when computing the length - of instructions. Ugh. We could walk the insn chain to - determine if this instruction is in a branch table, but - that can get rather expensive, particularly during the - branch shortening phase of the compiler. - - So instead we mark this jump as being special. This is - far from ideal and knows that no code after this will - muck around with the mode of the JUMP_INSN itself. */ - PUT_MODE (tmp, SImode); - LABEL_NUSES (JUMP_LABEL (tmp))++; - location = NEXT_INSN (location); - } - - /* Emit a BARRIER after the jump. */ - emit_barrier_after (location); - location = NEXT_INSN (location); - } - - /* Emit marker for the end of the branch table. */ - emit_insn_before (gen_end_brtab (), location); - location = NEXT_INSN (location); - emit_barrier_after (location); - - /* Delete the ADDR_VEC or ADDR_DIFF_VEC. */ - delete_insn (insn); - } - } - else - { - /* Sill need an end_brtab insn. */ - insns = get_insns (); - for (insn = insns; insn; insn = NEXT_INSN (insn)) - { - /* Find an ADDR_VEC insn. */ - if (GET_CODE (insn) != JUMP_INSN - || (GET_CODE (PATTERN (insn)) != ADDR_VEC - && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)) - continue; - - /* Now generate markers for the beginning and end of the - branch table. */ - emit_insn_before (gen_begin_brtab (), insn); - emit_insn_after (gen_end_brtab (), insn); - } - } -} - -/* The PA has a number of odd instructions which can perform multiple - tasks at once. On first generation PA machines (PA1.0 and PA1.1) - it may be profitable to combine two instructions into one instruction - with two outputs. It's not profitable PA2.0 machines because the - two outputs would take two slots in the reorder buffers. - - This routine finds instructions which can be combined and combines - them. We only support some of the potential combinations, and we - only try common ways to find suitable instructions. - - * addb can add two registers or a register and a small integer - and jump to a nearby (+-8k) location. Normally the jump to the - nearby location is conditional on the result of the add, but by - using the "true" condition we can make the jump unconditional. - Thus addb can perform two independent operations in one insn. - - * movb is similar to addb in that it can perform a reg->reg - or small immediate->reg copy and jump to a nearby (+-8k location). - - * fmpyadd and fmpysub can perform a FP multiply and either an - FP add or FP sub if the operands of the multiply and add/sub are - independent (there are other minor restrictions). Note both - the fmpy and fadd/fsub can in theory move to better spots according - to data dependencies, but for now we require the fmpy stay at a - fixed location. - - * Many of the memory operations can perform pre & post updates - of index registers. GCC's pre/post increment/decrement addressing - is far too simple to take advantage of all the possibilities. This - pass may not be suitable since those insns may not be independent. - - * comclr can compare two ints or an int and a register, nullify - the following instruction and zero some other register. This - is more difficult to use as it's harder to find an insn which - will generate a comclr than finding something like an unconditional - branch. (conditional moves & long branches create comclr insns). - - * Most arithmetic operations can conditionally skip the next - instruction. They can be viewed as "perform this operation - and conditionally jump to this nearby location" (where nearby - is an insns away). These are difficult to use due to the - branch length restrictions. */ - -static void -pa_combine_instructions (insns) - rtx insns ATTRIBUTE_UNUSED; -{ - rtx anchor, new; - - /* This can get expensive since the basic algorithm is on the - order of O(n^2) (or worse). Only do it for -O2 or higher - levels of optimization. */ - if (optimize < 2) - return; - - /* Walk down the list of insns looking for "anchor" insns which - may be combined with "floating" insns. As the name implies, - "anchor" instructions don't move, while "floating" insns may - move around. */ - new = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, NULL_RTX, NULL_RTX)); - new = make_insn_raw (new); - - for (anchor = get_insns (); anchor; anchor = NEXT_INSN (anchor)) - { - enum attr_pa_combine_type anchor_attr; - enum attr_pa_combine_type floater_attr; - - /* We only care about INSNs, JUMP_INSNs, and CALL_INSNs. - Also ignore any special USE insns. */ - if ((GET_CODE (anchor) != INSN - && GET_CODE (anchor) != JUMP_INSN - && GET_CODE (anchor) != CALL_INSN) - || GET_CODE (PATTERN (anchor)) == USE - || GET_CODE (PATTERN (anchor)) == CLOBBER - || GET_CODE (PATTERN (anchor)) == ADDR_VEC - || GET_CODE (PATTERN (anchor)) == ADDR_DIFF_VEC) - continue; - - anchor_attr = get_attr_pa_combine_type (anchor); - /* See if anchor is an insn suitable for combination. */ - if (anchor_attr == PA_COMBINE_TYPE_FMPY - || anchor_attr == PA_COMBINE_TYPE_FADDSUB - || (anchor_attr == PA_COMBINE_TYPE_UNCOND_BRANCH - && ! forward_branch_p (anchor))) - { - rtx floater; - - for (floater = PREV_INSN (anchor); - floater; - floater = PREV_INSN (floater)) - { - if (GET_CODE (floater) == NOTE - || (GET_CODE (floater) == INSN - && (GET_CODE (PATTERN (floater)) == USE - || GET_CODE (PATTERN (floater)) == CLOBBER))) - continue; - - /* Anything except a regular INSN will stop our search. */ - if (GET_CODE (floater) != INSN - || GET_CODE (PATTERN (floater)) == ADDR_VEC - || GET_CODE (PATTERN (floater)) == ADDR_DIFF_VEC) - { - floater = NULL_RTX; - break; - } - - /* See if FLOATER is suitable for combination with the - anchor. */ - floater_attr = get_attr_pa_combine_type (floater); - if ((anchor_attr == PA_COMBINE_TYPE_FMPY - && floater_attr == PA_COMBINE_TYPE_FADDSUB) - || (anchor_attr == PA_COMBINE_TYPE_FADDSUB - && floater_attr == PA_COMBINE_TYPE_FMPY)) - { - /* If ANCHOR and FLOATER can be combined, then we're - done with this pass. */ - if (pa_can_combine_p (new, anchor, floater, 0, - SET_DEST (PATTERN (floater)), - XEXP (SET_SRC (PATTERN (floater)), 0), - XEXP (SET_SRC (PATTERN (floater)), 1))) - break; - } - - else if (anchor_attr == PA_COMBINE_TYPE_UNCOND_BRANCH - && floater_attr == PA_COMBINE_TYPE_ADDMOVE) - { - if (GET_CODE (SET_SRC (PATTERN (floater))) == PLUS) - { - if (pa_can_combine_p (new, anchor, floater, 0, - SET_DEST (PATTERN (floater)), - XEXP (SET_SRC (PATTERN (floater)), 0), - XEXP (SET_SRC (PATTERN (floater)), 1))) - break; - } - else - { - if (pa_can_combine_p (new, anchor, floater, 0, - SET_DEST (PATTERN (floater)), - SET_SRC (PATTERN (floater)), - SET_SRC (PATTERN (floater)))) - break; - } - } - } - - /* If we didn't find anything on the backwards scan try forwards. */ - if (!floater - && (anchor_attr == PA_COMBINE_TYPE_FMPY - || anchor_attr == PA_COMBINE_TYPE_FADDSUB)) - { - for (floater = anchor; floater; floater = NEXT_INSN (floater)) - { - if (GET_CODE (floater) == NOTE - || (GET_CODE (floater) == INSN - && (GET_CODE (PATTERN (floater)) == USE - || GET_CODE (PATTERN (floater)) == CLOBBER))) - - continue; - - /* Anything except a regular INSN will stop our search. */ - if (GET_CODE (floater) != INSN - || GET_CODE (PATTERN (floater)) == ADDR_VEC - || GET_CODE (PATTERN (floater)) == ADDR_DIFF_VEC) - { - floater = NULL_RTX; - break; - } - - /* See if FLOATER is suitable for combination with the - anchor. */ - floater_attr = get_attr_pa_combine_type (floater); - if ((anchor_attr == PA_COMBINE_TYPE_FMPY - && floater_attr == PA_COMBINE_TYPE_FADDSUB) - || (anchor_attr == PA_COMBINE_TYPE_FADDSUB - && floater_attr == PA_COMBINE_TYPE_FMPY)) - { - /* If ANCHOR and FLOATER can be combined, then we're - done with this pass. */ - if (pa_can_combine_p (new, anchor, floater, 1, - SET_DEST (PATTERN (floater)), - XEXP (SET_SRC (PATTERN(floater)),0), - XEXP(SET_SRC(PATTERN(floater)),1))) - break; - } - } - } - - /* FLOATER will be nonzero if we found a suitable floating - insn for combination with ANCHOR. */ - if (floater - && (anchor_attr == PA_COMBINE_TYPE_FADDSUB - || anchor_attr == PA_COMBINE_TYPE_FMPY)) - { - /* Emit the new instruction and delete the old anchor. */ - emit_insn_before (gen_rtx_PARALLEL (VOIDmode, - gen_rtvec (2, - PATTERN (anchor), - PATTERN (floater))), - anchor); - PUT_CODE (anchor, NOTE); - NOTE_LINE_NUMBER (anchor) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (anchor) = 0; - - /* Emit a special USE insn for FLOATER, then delete - the floating insn. */ - emit_insn_before (gen_rtx_USE (VOIDmode, floater), floater); - delete_insn (floater); - - continue; - } - else if (floater - && anchor_attr == PA_COMBINE_TYPE_UNCOND_BRANCH) - { - rtx temp; - /* Emit the new_jump instruction and delete the old anchor. */ - temp = emit_jump_insn_before (gen_rtx_PARALLEL (VOIDmode, - gen_rtvec (2, PATTERN (anchor), - PATTERN (floater))), - anchor); - JUMP_LABEL (temp) = JUMP_LABEL (anchor); - PUT_CODE (anchor, NOTE); - NOTE_LINE_NUMBER (anchor) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (anchor) = 0; - - /* Emit a special USE insn for FLOATER, then delete - the floating insn. */ - emit_insn_before (gen_rtx_USE (VOIDmode, floater), floater); - delete_insn (floater); - continue; - } - } - } -} - -int -pa_can_combine_p (new, anchor, floater, reversed, dest, src1, src2) - rtx new, anchor, floater; - int reversed; - rtx dest, src1, src2; -{ - int insn_code_number; - rtx start, end; - - /* Create a PARALLEL with the patterns of ANCHOR and - FLOATER, try to recognize it, then test constraints - for the resulting pattern. - - If the pattern doesn't match or the constraints - aren't met keep searching for a suitable floater - insn. */ - XVECEXP (PATTERN (new), 0, 0) = PATTERN (anchor); - XVECEXP (PATTERN (new), 0, 1) = PATTERN (floater); - INSN_CODE (new) = -1; - insn_code_number = recog_memoized (new); - if (insn_code_number < 0 - || !constrain_operands (insn_code_number, 1)) - return 0; - - if (reversed) - { - start = anchor; - end = floater; - } - else - { - start = floater; - end = anchor; - } - - /* There's up to three operands to consider. One - output and two inputs. - - The output must not be used between FLOATER & ANCHOR - exclusive. The inputs must not be set between - FLOATER and ANCHOR exclusive. */ - - if (reg_used_between_p (dest, start, end)) - return 0; - - if (reg_set_between_p (src1, start, end)) - return 0; - - if (reg_set_between_p (src2, start, end)) - return 0; - - /* If we get here, then everything is good. */ - return 1; -} - -/* Return nonzero if sets and references for INSN are delayed. - - Millicode insns are actually function calls with some special - constraints on arguments and register usage. - - Millicode calls always expect their arguments in the integer argument - registers, and always return their result in %r29 (ret1). They - are expected to clobber their arguments, %r1, %r29, and %r31 and - nothing else. - - By considering this effects delayed reorg reorg can put insns - which set the argument registers into the delay slot of the millicode - call -- thus they act more like traditional CALL_INSNs. - - get_attr_type will try to recognize the given insn, so make sure to - filter out things it will not accept -- SEQUENCE, USE and CLOBBER insns - in particular. */ -int -insn_sets_and_refs_are_delayed (insn) - rtx insn; -{ - return ((GET_CODE (insn) == INSN - && GET_CODE (PATTERN (insn)) != SEQUENCE - && GET_CODE (PATTERN (insn)) != USE - && GET_CODE (PATTERN (insn)) != CLOBBER - && get_attr_type (insn) == TYPE_MILLI)); -} diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h deleted file mode 100755 index a63d955..0000000 --- a/gcc/config/pa/pa.h +++ /dev/null @@ -1,2601 +0,0 @@ -/* Definitions of target machine for GNU compiler, for the HP Spectrum. - Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc. - Contributed by Michael Tiemann (tiemann@cygnus.com) of Cygnus Support - and Tim Moore (moore@defmacro.cs.utah.edu) of the Center for - Software Science at the University of Utah. - -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 1, 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. */ - -enum cmp_type /* comparison type */ -{ - CMP_SI, /* compare integers */ - CMP_SF, /* compare single precision floats */ - CMP_DF, /* compare double precision floats */ - CMP_MAX /* max comparison type */ -}; - -/* For long call handling. */ -extern unsigned int total_code_bytes; - -/* Which processor to schedule for. */ - -enum processor_type -{ - PROCESSOR_700, - PROCESSOR_7100, - PROCESSOR_7100LC, - PROCESSOR_7200, - /* CYGNUS LOCAL PA8000/law */ - PROCESSOR_8000 - /* END CYGNUS LCOAL */ -}; - -/* For -mschedule= option. */ -extern char *pa_cpu_string; -extern enum processor_type pa_cpu; - -#define pa_cpu_attr ((enum attr_cpu)pa_cpu) - -/* CYGNUS LOCAL PA8000/law */ -/* The 700 can only issue a single insn at a time. - The 7XXX processors can issue two insns at a time. */ -#define ISSUE_RATE \ - (pa_cpu == PROCESSOR_700 ? 1 : pa_cpu == PROCESSOR_8000 ? 4 : 2) -/* END CYGNUS LOCAL */ - -/* Print subsidiary information on the compiler version in use. */ - -#define TARGET_VERSION fputs (" (hppa)", stderr); - -/* Run-time compilation parameters selecting different hardware subsets. */ - -extern int target_flags; - -/* compile code for HP-PA 1.1 ("Snake") */ - -#define TARGET_SNAKE (target_flags & 1) - -/* Disable all FP registers (they all become fixed). This may be necessary - for compiling kernels which perform lazy context switching of FP regs. - Note if you use this option and try to perform floating point operations - the compiler will abort! */ - -#define TARGET_DISABLE_FPREGS (target_flags & 2) - -/* Generate code which assumes that calls through function pointers will - never cross a space boundary. Such assumptions are generally safe for - building kernels and statically linked executables. Code compiled with - this option will fail miserably if the executable is dynamically linked - or uses nested functions! - - This is also used to trigger aggressive unscaled index addressing. */ -#define TARGET_NO_SPACE_REGS (target_flags & 4) - -/* Allow unconditional jumps in the delay slots of call instructions. */ -#define TARGET_JUMP_IN_DELAY (target_flags & 8) - -/* Optimize for space. Currently this only turns on out of line - prologues and epilogues. */ -#define TARGET_SPACE (target_flags & 16) - -/* Disable indexed addressing modes. */ - -#define TARGET_DISABLE_INDEXING (target_flags & 32) - -/* Emit code which follows the new portable runtime calling conventions - HP wants everyone to use for ELF objects. If at all possible you want - to avoid this since it's a performance loss for non-prototyped code. - - Note TARGET_PORTABLE_RUNTIME also forces all calls to use inline - long-call stubs which is quite expensive. */ - -#define TARGET_PORTABLE_RUNTIME (target_flags & 64) - -/* Emit directives only understood by GAS. This allows parameter - relocations to work for static functions. There is no way - to make them work the HP assembler at this time. */ - -#define TARGET_GAS (target_flags & 128) - -/* Emit code for processors which do not have an FPU. */ - -#define TARGET_SOFT_FLOAT (target_flags & 256) - -/* Use 3-insn load/store sequences for access to large data segments - in shared libraries on hpux10. */ -#define TARGET_LONG_LOAD_STORE (target_flags & 512) - -/* Use a faster sequence for indirect calls. */ -#define TARGET_FAST_INDIRECT_CALLS (target_flags & 1024) - -/* Generate code with big switch statements to avoid out of range branches - occurring within the switch table. */ -#define TARGET_BIG_SWITCH (target_flags & 2048) - -/* CYGNUS LOCAL pa8000/law */ -/* Generate PA2.0 instructions. */ -#define TARGET_PARISC_2_0 (target_flags & 4096) -/* END CYGNUS LOCAL */ - -/* 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 \ - {{"snake", 1}, \ - {"nosnake", -1}, \ - {"pa-risc-1-0", -1}, \ - {"pa-risc-1-1", 1}, \ - {"disable-fpregs", 2}, \ - {"no-disable-fpregs", -2}, \ - {"no-space-regs", 4}, \ - {"space-regs", -4}, \ - {"jump-in-delay", 8}, \ - {"no-jump-in-delay", -8}, \ - {"space", 16}, \ - {"no-space", -16}, \ - {"disable-indexing", 32}, \ - {"no-disable-indexing", -32},\ - {"portable-runtime", 64}, \ - {"no-portable-runtime", -64},\ - {"gas", 128}, \ - {"no-gas", -128}, \ - {"soft-float", 256}, \ - {"no-soft-float", -256}, \ - {"long-load-store", 512}, \ - {"no-long-load-store", -512},\ - {"fast-indirect-calls", 1024},\ - {"no-fast-indirect-calls", -1024},\ - {"big-switch", 2048}, \ - {"no-big-switch", -2048}, \ - /* CYGNUS LOCAL pa8000/law */\ - {"pa-risc-2-0", 4097}, \ - {"no-pa-risc-2-0", -4096}, \ - /* END CYGNUS LOCAL */ \ - {"linker-opt", 0}, \ - { "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}} - -#ifndef TARGET_DEFAULT -#define TARGET_DEFAULT 0x88 /* TARGET_GAS + TARGET_JUMP_IN_DELAY */ -#endif - -#ifndef TARGET_CPU_DEFAULT -#define TARGET_CPU_DEFAULT 0 -#endif - -#define TARGET_OPTIONS \ -{ \ - { "schedule=", &pa_cpu_string }\ -} - -#define OVERRIDE_OPTIONS override_options () - -#define DBX_DEBUGGING_INFO -#define DEFAULT_GDB_EXTENSIONS 1 - -/* This is the way other stabs-in-XXX tools do things. We will be - compatible. */ -#define DBX_BLOCKS_FUNCTION_RELATIVE 1 - -/* Likewise for linenos. - - We make the first line stab special to avoid adding several - gross hacks to GAS. */ -#undef ASM_OUTPUT_SOURCE_LINE -#define ASM_OUTPUT_SOURCE_LINE(file, line) \ - { static int sym_lineno = 1; \ - static tree last_function_decl = NULL; \ - if (current_function_decl == last_function_decl) \ - fprintf (file, "\t.stabn 68,0,%d,L$M%d-%s\nL$M%d:\n", \ - line, sym_lineno, \ - XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0) + 1, \ - sym_lineno); \ - else \ - fprintf (file, "\t.stabn 68,0,%d,0\n", line); \ - last_function_decl = current_function_decl; \ - sym_lineno += 1; } - -/* But, to make this work, we have to output the stabs for the function - name *first*... */ -#define DBX_FUNCTION_FIRST - -/* Only labels should ever begin in column zero. */ -#define ASM_STABS_OP "\t.stabs" -#define ASM_STABN_OP "\t.stabn" - -/* GDB always assumes the current function's frame begins at the value - of the stack pointer upon entry to the current function. Accessing - local variables and parameters passed on the stack is done using the - base of the frame + an offset provided by GCC. - - For functions which have frame pointers this method works fine; - the (frame pointer) == (stack pointer at function entry) and GCC provides - an offset relative to the frame pointer. - - This loses for functions without a frame pointer; GCC provides an offset - which is relative to the stack pointer after adjusting for the function's - frame size. GDB would prefer the offset to be relative to the value of - the stack pointer at the function's entry. Yuk! */ -#define DEBUGGER_AUTO_OFFSET(X) \ - ((GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0) \ - + (frame_pointer_needed ? 0 : compute_frame_size (get_frame_size (), 0))) - -#define DEBUGGER_ARG_OFFSET(OFFSET, X) \ - ((GET_CODE (X) == PLUS ? OFFSET : 0) \ - + (frame_pointer_needed ? 0 : compute_frame_size (get_frame_size (), 0))) - -/* gdb needs a null N_SO at the end of each file for scattered loading. */ - -#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END -#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \ - text_section (); \ - if (!TARGET_PORTABLE_RUNTIME) \ - fputs ("\t.SPACE $TEXT$\n\t.NSUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n", FILE); \ - else \ - fprintf (FILE, "%s\n", TEXT_SECTION_ASM_OP); \ - fprintf (FILE, \ - "\t.stabs \"\",%d,0,0,L$text_end0000\nL$text_end0000:\n", N_SO) - -/* CYGNUS LOCAL hpux11/law */ -#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1) == 0 -#define CPP_SPEC "%{msnake:-D__hp9000s700 -D_PA_RISC1_1}\ - %{mpa-risc-1-1:-D__hp9000s700 -D_PA_RISC1_1}\ - %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE -D__STDC_EXT__}\ - %{threads:-D_REENTRANT -D_DCE_THREADS}" -#else -#define CPP_SPEC "%{!mpa-risc-1-0:%{!mnosnake:%{!msoft-float:-D__hp9000s700 -D_PA_RISC1_1}}} \ - %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE -D__STDC_EXT__}\ - %{threads:-D_REENTRANT -D_DCE_THREADS}" -#endif -/* END CYGNUS LOCAL */ - -/* Defines for a K&R CC */ - -#define CC1_SPEC "%{pg:} %{p:}" - -#define LINK_SPEC "%{mlinker-opt:-O} %{!shared:-u main} %{shared:-b}" - -/* We don't want -lg. */ -#ifndef LIB_SPEC -#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}" -#endif - -/* Make gcc agree with <machine/ansi.h> */ - -#define SIZE_TYPE "unsigned int" -#define PTRDIFF_TYPE "int" -#define WCHAR_TYPE "unsigned int" -#define WCHAR_TYPE_SIZE 32 - -/* Show we can debug even without a frame pointer. */ -#define CAN_DEBUG_WITHOUT_FP - -/* Machine dependent reorg pass. */ -#define MACHINE_DEPENDENT_REORG(X) pa_reorg(X) - -/* Prototype function used in MACHINE_DEPENDENT_REORG macro. */ -void pa_reorg (); - -/* Prototype function used in various macros. */ -int symbolic_operand (); - -/* Used in insn-*.c. */ -int following_call (); -int function_label_operand (); -int lhs_lshift_cint_operand (); - -/* Names to predefine in the preprocessor for this target machine. */ - -#define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -Dunix -Dhp9000 -Dhp800 -Dspectrum -DREVARGV -Asystem(unix) -Asystem(bsd) -Acpu(hppa) -Amachine(hppa)" - -/* HPUX has a program 'chatr' to list the dependencies of dynamically - linked executables and shared libraries. */ -#define LDD_SUFFIX "chatr" -/* Look for lines like "dynamic /usr/lib/X11R5/libX11.sl" - or "static /usr/lib/X11R5/libX11.sl". - - HPUX 10.20 also has lines like "static branch prediction ..." - so we filter that out explicitly. - - We also try to bound our search for libraries with marker - lines. What a pain. */ -#define PARSE_LDD_OUTPUT(PTR) \ -do { \ - static int in_shlib_list = 0; \ - while (*PTR == ' ') PTR++; \ - if (strncmp (PTR, "shared library list:", \ - sizeof ("shared library list:") - 1) == 0) \ - { \ - PTR = 0; \ - in_shlib_list = 1; \ - } \ - else if (strncmp (PTR, "shared library binding:", \ - sizeof ("shared library binding:") - 1) == 0)\ - { \ - PTR = 0; \ - in_shlib_list = 0; \ - } \ - else if (strncmp (PTR, "static branch prediction disabled", \ - sizeof ("static branch prediction disabled") - 1) == 0)\ - { \ - PTR = 0; \ - in_shlib_list = 0; \ - } \ - else if (in_shlib_list \ - && strncmp (PTR, "dynamic", sizeof ("dynamic") - 1) == 0) \ - { \ - PTR += sizeof ("dynamic") - 1; \ - while (*p == ' ') PTR++; \ - } \ - else if (in_shlib_list \ - && strncmp (PTR, "static", sizeof ("static") - 1) == 0) \ - { \ - PTR += sizeof ("static") - 1; \ - while (*p == ' ') PTR++; \ - } \ - else \ - PTR = 0; \ -} while (0) - -/* target machine storage layout */ - -/* Define for cross-compilation from a host with a different float format - or endianness (e.g. VAX, x86). */ -#define REAL_ARITHMETIC - -/* 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. */ - -#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \ - if (GET_MODE_CLASS (MODE) == MODE_INT \ - && GET_MODE_SIZE (MODE) < 4) \ - (MODE) = SImode; - -/* Define this if most significant bit is lowest numbered - in instructions that operate on numbered bit-fields. */ -#define BITS_BIG_ENDIAN 1 - -/* Define this if most significant byte of a word is the lowest numbered. */ -/* That is true on the HP-PA. */ -#define BYTES_BIG_ENDIAN 1 - -/* Define this if most significant word of a multiword number is lowest - numbered. */ -#define WORDS_BIG_ENDIAN 1 - -/* 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 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 32 - -/* Largest alignment required for any stack parameter, in bits. - Don't define this if it is equal to PARM_BOUNDARY */ -#define MAX_PARM_BOUNDARY 64 - -/* Boundary (in *bits*) on which stack pointer is always aligned; - certain optimizations in combine depend on this. - - GCC for the PA always rounds its stacks to a 512bit boundary, - but that happens late in the compilation process. */ -#define STACK_BOUNDARY 64 - -/* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 32 - -/* Alignment of field after `int : 0' in a structure. */ -#define EMPTY_FIELD_BOUNDARY 32 - -/* Every structure's size must be a multiple of this. */ -#define STRUCTURE_SIZE_BOUNDARY 8 - -/* A bitfield declared as `int' forces `int' alignment for the struct. */ -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* No data type wants to be aligned rounder than this. */ -#define BIGGEST_ALIGNMENT 64 - -/* The .align directive in the HP assembler allows up to a 32 alignment. */ -#define MAX_OFILE_ALIGNMENT 32768 - -/* Get around hp-ux assembler bug, and make strcpy of constants fast. */ -#define CONSTANT_ALIGNMENT(CODE, TYPEALIGN) \ - ((TYPEALIGN) < 32 ? 32 : (TYPEALIGN)) - -/* Make arrays of chars word-aligned for the same reasons. */ -#define DATA_ALIGNMENT(TYPE, ALIGN) \ - (TREE_CODE (TYPE) == ARRAY_TYPE \ - && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) - - -/* Set this nonzero if move instructions will actually fail to work - when given unaligned data. */ -#define STRICT_ALIGNMENT 1 - -/* Generate calls to memcpy, memcmp and memset. */ -#define TARGET_MEM_FUNCTIONS - -/* 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. - - HP-PA 1.0 has 32 fullword registers and 16 floating point - registers. The floating point registers hold either word or double - word values. - - 16 additional registers are reserved. - - HP-PA 1.1 has 32 fullword registers and 32 floating point - registers. However, the floating point registers behave - differently: the left and right halves of registers are addressable - as 32 bit registers. So, we will set things up like the 68k which - has different fp units: define separate register sets for the 1.0 - and 1.1 fp units. */ - -#define FIRST_PSEUDO_REGISTER 89 /* 32 general regs + 56 fp regs + - + 1 shift reg */ - -/* 1 for registers that have pervasive standard uses - and are not available for the register allocator. - - On the HP-PA, these are: - Reg 0 = 0 (hardware). However, 0 is used for condition code, - so is not fixed. - Reg 1 = ADDIL target/Temporary (hardware). - Reg 2 = Return Pointer - Reg 3 = Frame Pointer - Reg 4 = Frame Pointer (>8k varying frame with HP compilers only) - Reg 4-18 = Preserved Registers - Reg 19 = Linkage Table Register in HPUX 8.0 shared library scheme. - Reg 20-22 = Temporary Registers - Reg 23-26 = Temporary/Parameter Registers - Reg 27 = Global Data Pointer (hp) - Reg 28 = Temporary/???/Return Value register - Reg 29 = Temporary/Static Chain/Return Value register #2 - Reg 30 = stack pointer - Reg 31 = Temporary/Millicode Return Pointer (hp) - - Freg 0-3 = Status Registers -- Not known to the compiler. - Freg 4-7 = Arguments/Return Value - Freg 8-11 = Temporary Registers - Freg 12-15 = Preserved Registers - - Freg 16-31 = Reserved - - On the Snake, fp regs are - - Freg 0-3 = Status Registers -- Not known to the compiler. - Freg 4L-7R = Arguments/Return Value - Freg 8L-11R = Temporary Registers - Freg 12L-21R = Preserved Registers - Freg 22L-31R = Temporary Registers - -*/ - -#define FIXED_REGISTERS \ - {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, 0, 0, 1, 0, 0, 1, 0, \ - /* fp registers */ \ - 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, 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, 0, 0, 0, 0, 0, 0, \ - 0} - -/* 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, 1, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - /* fp registers */ \ - 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, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - 1} - -#define CONDITIONAL_REGISTER_USAGE \ -{ \ - if (!TARGET_SNAKE) \ - { \ - for (i = 56; i < 88; i++) \ - fixed_regs[i] = call_used_regs[i] = 1; \ - for (i = 33; i < 88; i += 2) \ - fixed_regs[i] = call_used_regs[i] = 1; \ - } \ - if (TARGET_DISABLE_FPREGS || TARGET_SOFT_FLOAT)\ - { \ - for (i = 32; i < 88; i++) \ - fixed_regs[i] = call_used_regs[i] = 1; \ - } \ - if (flag_pic) \ - { \ - fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \ - fixed_regs[PIC_OFFSET_TABLE_REGNUM_SAVED] = 1;\ - } \ -} - -/* CYGNUS LOCAL PA8000/law */ -/* Allocate the call used registers first. This should minimize - the number of registers that need to be saved (as call used - registers will generally not be allocated across a call). - - Experimentation has shown slightly better results by allocating - FP registers first. - - The PA8000 triggers a depedency stall if we use both halves of a - floating point register in the same bundle. So we separate out the - halves to discourage using them in nearby insns. This should be - fixed in the register allocator/scheduler. */ - -#define REG_ALLOC_ORDER \ - { \ - /* caller-saved fp regs. */ \ - 68, 70, 72, 74, 76, 78, 80, 82, \ - 84, 86, 40, 42, 44, 46, 32, 34, \ - 36, 38, \ - 69, 71, 73, 75, 77, 79, 81, 83, \ - 85, 87, 41, 43, 45, 47, 33, 35, \ - 37, 39, \ - /* caller-saved general regs. */ \ - 19, 20, 21, 22, 23, 24, 25, 26, \ - 27, 28, 29, 31, 2, \ - /* callee-saved fp regs. */ \ - 48, 50, 52, 54, 56, 58, 60, 62, \ - 64, 66, \ - 49, 51, 53, 55, 57, 59, 61, 63, \ - 65, 67, \ - /* callee-saved general regs. */ \ - 3, 4, 5, 6, 7, 8, 9, 10, \ - 11, 12, 13, 14, 15, 16, 17, 18, \ - /* special registers. */ \ - 1, 30, 0, 88} -/* END CYGNUS LOCAL */ - - -/* True if register is floating-point. */ -#define FP_REGNO_P(N) ((N) >= 32 && (N) <= 87) - -/* 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. - - On the HP-PA, ordinary registers hold 32 bits worth; - The floating point registers are 64 bits wide. Snake fp regs are 32 - bits wide */ -#define HARD_REGNO_NREGS(REGNO, MODE) \ - (!TARGET_SNAKE && FP_REGNO_P (REGNO) ? 1 \ - : ((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. - On the HP-PA, the cpu registers can hold any mode. We - force this to be an even register is it cannot hold the full mode. */ -#define HARD_REGNO_MODE_OK(REGNO, MODE) \ - ((REGNO) == 0 ? (MODE) == CCmode || (MODE) == CCFPmode \ - /* On 1.0 machines, don't allow wide non-fp modes in fp regs. */ \ - : !TARGET_SNAKE && FP_REGNO_P (REGNO) \ - ? GET_MODE_SIZE (MODE) <= 4 || GET_MODE_CLASS (MODE) == MODE_FLOAT \ - /* Make wide modes be in aligned registers. */ \ - : GET_MODE_SIZE (MODE) <= 4 || ((REGNO) & 1) == 0) - -/* 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) \ - (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2)) - -/* Specify the registers used for certain standard purposes. - The values of these macros are register numbers. */ - -/* The HP-PA pc isn't overloaded on a register that the compiler knows about. */ -/* #define PC_REGNUM */ - -/* Register to use for pushing function arguments. */ -#define STACK_POINTER_REGNUM 30 - -/* Base register for access to local variables of the function. */ -#define FRAME_POINTER_REGNUM 3 - -/* Value should be nonzero if functions must have frame pointers. */ -#define FRAME_POINTER_REQUIRED \ - (current_function_calls_alloca) - -/* C statement to store the difference between the frame pointer - and the stack pointer values immediately after the function prologue. - - Note, we always pretend that this is a leaf function because if - it's not, there's no point in trying to eliminate the - frame pointer. If it is a leaf function, we guessed right! */ -#define INITIAL_FRAME_POINTER_OFFSET(VAR) \ - do {(VAR) = - compute_frame_size (get_frame_size (), 0);} while (0) - -/* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM 3 - -/* Register in which static-chain is passed to a function. */ -/* ??? */ -#define STATIC_CHAIN_REGNUM 29 - -/* Register which holds offset table for position-independent - data references. */ - -#define PIC_OFFSET_TABLE_REGNUM 19 -#define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED 1 - -/* Register into which we save the PIC_OFFEST_TABLE_REGNUM so that it - can be restore across function calls. */ -#define PIC_OFFSET_TABLE_REGNUM_SAVED 4 - -/* SOM ABI says that objects larger than 64 bits are returned in memory. */ -#define DEFAULT_PCC_STRUCT_RETURN 0 -#define RETURN_IN_MEMORY(TYPE) \ - (int_size_in_bytes (TYPE) > 8) - -/* Register in which address to store a structure value - is passed to a function. */ -#define STRUCT_VALUE_REGNUM 28 - -/* 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. */ - - /* The HP-PA has four kinds of registers: general regs, 1.0 fp regs, - 1.1 fp regs, and the high 1.1 fp regs, to which the operands of - fmpyadd and fmpysub are restricted. */ - -enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS, GENERAL_OR_FP_REGS, - SHIFT_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", "R1_REGS", "GENERAL_REGS", "FPUPPER_REGS", "FP_REGS", \ - "GENERAL_OR_FP_REGS", "SHIFT_REGS", "ALL_REGS"} - -/* Define which registers fit in which classes. - This is an initializer for a vector of HARD_REG_SET - of length N_REG_CLASSES. Register 0, the "condition code" register, - is in no class. */ - -#define REG_CLASS_CONTENTS \ - {{0x00000000, 0x00000000, 0x00000000}, /* NO_REGS */ \ - {0x00000002, 0x00000000, 0x00000000}, /* R1_REGS */ \ - {0xfffffffe, 0x00000000, 0x00000000}, /* GENERAL_REGS */ \ - {0x00000000, 0xff000000, 0x00ffffff}, /* FPUPPER_REGS */ \ - {0x00000000, 0xffffffff, 0x00ffffff}, /* FP_REGS */ \ - {0xfffffffe, 0xffffffff, 0x00ffffff}, /* GENERAL_OR_FP_REGS */ \ - {0x00000000, 0x00000000, 0x01000000}, /* SHIFT_REGS */ \ - {0xfffffffe, 0xffffffff, 0x01ffffff}} /* 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) \ - ((REGNO) == 0 ? NO_REGS \ - : (REGNO) == 1 ? R1_REGS \ - : (REGNO) < 32 ? GENERAL_REGS \ - : (REGNO) < 56 ? FP_REGS \ - : (REGNO) < 88 ? FPUPPER_REGS \ - : SHIFT_REGS) - -/* The class value for index registers, and the one for base regs. */ -#define INDEX_REG_CLASS GENERAL_REGS -#define BASE_REG_CLASS GENERAL_REGS - -#define FP_REG_CLASS_P(CLASS) \ - ((CLASS) == FP_REGS || (CLASS) == FPUPPER_REGS) - -/* Get reg_class from a letter such as appears in the machine description. */ -/* Keep 'x' for backward compatibility with user asm. */ -#define REG_CLASS_FROM_LETTER(C) \ - ((C) == 'f' ? FP_REGS : \ - (C) == 'y' ? FPUPPER_REGS : \ - (C) == 'x' ? FP_REGS : \ - (C) == 'q' ? SHIFT_REGS : \ - (C) == 'a' ? R1_REGS : \ - (C) == 'Z' ? ALL_REGS : NO_REGS) - -/* The letters I, J, K, L and M 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. - - `I' is used for the 11 bit constants. - `J' is used for the 14 bit constants. - `K' is used for values that can be moved with a zdepi insn. - `L' is used for the 5 bit constants. - `M' is used for 0. - `N' is used for values with the least significant 11 bits equal to zero. - `O' is used for numbers n such that n+1 is a power of 2. - */ - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? VAL_11_BITS_P (VALUE) \ - : (C) == 'J' ? VAL_14_BITS_P (VALUE) \ - : (C) == 'K' ? zdepi_cint_p (VALUE) \ - : (C) == 'L' ? VAL_5_BITS_P (VALUE) \ - : (C) == 'M' ? (VALUE) == 0 \ - : (C) == 'N' ? ((VALUE) & 0x7ff) == 0 \ - : (C) == 'O' ? (((VALUE) & ((VALUE) + 1)) == 0) \ - : (C) == 'P' ? and_mask_p (VALUE) \ - : 0) - -/* Prototype function used in macro CONST_OK_FOR_LETTER_P. */ -int zdepi_cint_p (); - -/* Similar, but for floating or large integer constants, and defining letters - G and H. Here VALUE is the CONST_DOUBLE rtx itself. - - For PA, `G' is the floating-point constant zero. `H' is undefined. */ - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'G' ? (GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_FLOAT \ - && (VALUE) == CONST0_RTX (GET_MODE (VALUE))) \ - : 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 register class of a scratch register needed to copy IN into - or out of a register in CLASS in MODE. If it can be done directly - NO_REGS is returned. - - Avoid doing any work for the common case calls. */ - -#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \ - ((CLASS == BASE_REG_CLASS && GET_CODE (IN) == REG \ - && REGNO (IN) < FIRST_PSEUDO_REGISTER) \ - ? NO_REGS : secondary_reload_class (CLASS, MODE, IN)) - -/* On the PA it is not possible to directly move data between - GENERAL_REGS and FP_REGS. */ -#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \ - (FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2)) - -/* Return the stack location to use for secondary memory needed reloads. */ -#define SECONDARY_MEMORY_NEEDED_RTX(MODE) \ - gen_rtx_MEM (MODE, gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-16))) - -/* Return the maximum number of consecutive registers - needed to represent mode MODE in a register of class CLASS. */ -#define CLASS_MAX_NREGS(CLASS, MODE) \ - (!TARGET_SNAKE && ((CLASS) == FP_REGS || (CLASS) == FPUPPER_REGS) ? 1 : \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) - -/* 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 */ - -/* Believe it or not. */ -#define ARGS_GROW_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 8 - -/* If we generate an insn to push BYTES bytes, - this says how many the stack pointer really advances by. - On the HP-PA, don't define this because there are no push insns. */ -/* #define PUSH_ROUNDING(BYTES) */ - -/* Offset of first parameter from the argument pointer register value. - This value will be negated because the arguments grow down. - Also note that on STACK_GROWS_UPWARD machines (such as this one) - this is the distance from the frame pointer to the end of the first - argument, not it's beginning. To get the real offset of the first - argument, the size of the argument must be added. - - ??? Have to check on this.*/ - -#define FIRST_PARM_OFFSET(FNDECL) -32 - -/* Absolute value of offset from top-of-stack address to location to store the - function parameter if it can't go in a register. - Addresses for following parameters are computed relative to this one. */ -#define FIRST_PARM_CALLER_OFFSET(FNDECL) -32 - - -/* When a parameter is passed in a register, stack space is still - allocated for it. */ -#define REG_PARM_STACK_SPACE(DECL) 16 - -/* 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 - -/* Keep the stack pointer constant throughout the function. - This is both an optimization and a necessity: longjmp - doesn't behave itself when the stack pointer moves within - the function! */ -#define ACCUMULATE_OUTGOING_ARGS - -/* The weird HPPA calling conventions require a minimum of 48 bytes on - the stack: 16 bytes for register saves, and 32 bytes for magic. - This is the difference between the logical top of stack and the - actual sp. */ -#define STACK_POINTER_OFFSET -32 - -#define STACK_DYNAMIC_OFFSET(FNDECL) \ - ((STACK_POINTER_OFFSET) - current_function_outgoing_args_size) - -/* Value is 1 if returning from a function call automatically - pops the arguments described by the number-of-args field in the 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. */ - -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 - -/* 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. */ - -/* On the HP-PA the value is found in register(s) 28(-29), unless - the mode is SF or DF. Then the value is returned in fr4 (32, ) */ - - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx_REG (TYPE_MODE (VALTYPE), ((! TARGET_SOFT_FLOAT \ - && (TYPE_MODE (VALTYPE) == SFmode || \ - TYPE_MODE (VALTYPE) == DFmode)) ? \ - 32 : 28)) - -/* 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, \ - (! TARGET_SOFT_FLOAT \ - && ((MODE) == SFmode || (MODE) == DFmode) ? 32 : 28)) - -/* 1 if N is a possible register number for a function value - as seen by the caller. */ - -#define FUNCTION_VALUE_REGNO_P(N) \ - ((N) == 28 || (! TARGET_SOFT_FLOAT && (N) == 32)) - -/* 1 if N is a possible register number for function argument passing. */ - -#define FUNCTION_ARG_REGNO_P(N) \ - (((N) >= 23 && (N) <= 26) || (! TARGET_SOFT_FLOAT && (N) >= 32 && (N) <= 39)) - -/* 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. - - On the HP-PA, this is a single integer, which is a number of words - of arguments scanned so far (including the invisible argument, - if any, which holds the structure-value-address). - Thus 4 or more means all following args should go on the stack. */ - -struct hppa_args {int words, nargs_prototype, indirect; }; - -#define CUMULATIVE_ARGS struct hppa_args - -/* 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).words = 0, \ - (CUM).indirect = INDIRECT, \ - (CUM).nargs_prototype = (FNTYPE && TYPE_ARG_TYPES (FNTYPE) \ - ? (list_length (TYPE_ARG_TYPES (FNTYPE)) - 1 \ - + (TYPE_MODE (TREE_TYPE (FNTYPE)) == BLKmode \ - || RETURN_IN_MEMORY (TREE_TYPE (FNTYPE)))) \ - : 0) - - - -/* Similar, but when scanning the definition of a procedure. We always - set NARGS_PROTOTYPE large so we never return a PARALLEL. */ - -#define INIT_CUMULATIVE_INCOMING_ARGS(CUM,FNTYPE,IGNORE) \ - (CUM).words = 0, \ - (CUM).indirect = 0, \ - (CUM).nargs_prototype = 1000 - -/* Figure out the size in words of the function argument. */ - -#define FUNCTION_ARG_SIZE(MODE, TYPE) \ - ((((MODE) != BLKmode ? GET_MODE_SIZE (MODE) : int_size_in_bytes (TYPE))+3)/4) - -/* 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).nargs_prototype--; \ - ((((CUM).words & 01) && (TYPE) != 0 \ - && FUNCTION_ARG_SIZE(MODE, TYPE) > 1) \ - && (CUM).words++), \ - (CUM).words += FUNCTION_ARG_SIZE(MODE, TYPE); \ -} - -/* Determine where to put an argument 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). - - On the HP-PA the first four words of args are normally in registers - and the rest are pushed. But any arg that won't entirely fit in regs - is pushed. - - Arguments passed in registers are either 1 or 2 words long. - - The caller must make a distinction between calls to explicitly named - functions and calls through pointers to functions -- the conventions - are different! Calls through pointers to functions only use general - registers for the first four argument words. - - Of course all this is different for the portable runtime model - HP wants everyone to use for ELF. Ugh. Here's a quick description - of how it's supposed to work. - - 1) callee side remains unchanged. It expects integer args to be - in the integer registers, float args in the float registers and - unnamed args in integer registers. - - 2) caller side now depends on if the function being called has - a prototype in scope (rather than if it's being called indirectly). - - 2a) If there is a prototype in scope, then arguments are passed - according to their type (ints in integer registers, floats in float - registers, unnamed args in integer registers. - - 2b) If there is no prototype in scope, then floating point arguments - are passed in both integer and float registers. egad. - - FYI: The portable parameter passing conventions are almost exactly like - the standard parameter passing conventions on the RS6000. That's why - you'll see lots of similar code in rs6000.h. */ - -#define FUNCTION_ARG_PADDING(MODE, TYPE) function_arg_padding ((MODE), (TYPE)) - -/* Do not expect to understand this without reading it several times. I'm - tempted to try and simply it, but I worry about breaking something. */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - (4 >= ((CUM).words + FUNCTION_ARG_SIZE ((MODE), (TYPE))) \ - ? (!TARGET_PORTABLE_RUNTIME || (TYPE) == 0 \ - || !FLOAT_MODE_P (MODE) || TARGET_SOFT_FLOAT \ - || (CUM).nargs_prototype > 0) \ - ? gen_rtx_REG ((MODE), \ - (FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1 \ - ? (((!(CUM).indirect \ - || TARGET_PORTABLE_RUNTIME) \ - && (MODE) == DFmode \ - && ! TARGET_SOFT_FLOAT) \ - ? ((CUM).words ? 38 : 34) \ - : ((CUM).words ? 23 : 25)) \ - : (((!(CUM).indirect \ - || TARGET_PORTABLE_RUNTIME) \ - && (MODE) == SFmode \ - && ! TARGET_SOFT_FLOAT) \ - ? (32 + 2 * (CUM).words) \ - : (27 - (CUM).words - FUNCTION_ARG_SIZE ((MODE), \ - (TYPE))))))\ - /* We are calling a non-prototyped function with floating point \ - arguments using the portable conventions. */ \ - : gen_rtx_PARALLEL ((MODE), \ - gen_rtvec \ - (2, \ - gen_rtx_EXPR_LIST (VOIDmode, \ - gen_rtx_REG ((MODE), \ - (FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1 \ - ? ((CUM).words ? 38 : 34) \ - : (32 + 2 * (CUM).words))), \ - const0_rtx), \ - gen_rtx_EXPR_LIST (VOIDmode, \ - gen_rtx_REG ((MODE), \ - (FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1 \ - ? ((CUM).words ? 23 : 25) \ - : (27 - (CUM).words - \ - FUNCTION_ARG_SIZE ((MODE), \ - (TYPE))))), \ - const0_rtx))) \ - /* Pass this parameter in the stack. */ \ - : 0) - -/* For an arg passed partly in registers and partly in memory, - this is the number of registers used. - For args passed entirely in registers or entirely in memory, zero. */ - -#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0 - -/* If defined, a C expression that gives the alignment boundary, in - bits, of an argument with the specified mode and type. If it is - not defined, `PARM_BOUNDARY' is used for all arguments. */ - -#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ - (((TYPE) != 0) \ - ? (((int_size_in_bytes (TYPE)) + 3) / 4) * BITS_PER_WORD \ - : ((GET_MODE_ALIGNMENT(MODE) <= PARM_BOUNDARY) \ - ? PARM_BOUNDARY \ - : GET_MODE_ALIGNMENT(MODE))) - -/* Arguments larger than eight bytes are passed by invisible reference */ - -#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) - - -extern struct rtx_def *hppa_compare_op0, *hppa_compare_op1; -extern enum cmp_type hppa_branch_type; - -/* Output the label for a function definition. */ -#ifndef HP_FP_ARG_DESCRIPTOR_REVERSED -#define ASM_DOUBLE_ARG_DESCRIPTORS(FILE, ARG0, ARG1) \ - do { fprintf (FILE, ",ARGW%d=FR", (ARG0)); \ - fprintf (FILE, ",ARGW%d=FU", (ARG1));} while (0) -#define DFMODE_RETURN_STRING ",RTNVAL=FU" -#define SFMODE_RETURN_STRING ",RTNVAL=FR" -#else -#define ASM_DOUBLE_ARG_DESCRIPTORS(FILE, ARG0, ARG1) \ - do { fprintf (FILE, ",ARGW%d=FU", (ARG0)); \ - fprintf (FILE, ",ARGW%d=FR", (ARG1));} while (0) -#define DFMODE_RETURN_STRING ",RTNVAL=FR" -#define SFMODE_RETURN_STRING ",RTNVAL=FU" -#endif - -#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \ -{ char *target_name = XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0); \ - STRIP_NAME_ENCODING (target_name, target_name); \ - output_function_prologue (FILE, 0); \ - if (VAL_14_BITS_P (DELTA)) \ - fprintf (FILE, "\tb %s\n\tldo %d(%%r26),%%r26\n", target_name, DELTA); \ - else \ - fprintf (FILE, "\taddil L%%%d,%%r26\n\tb %s\n\tldo R%%%d(%%r1),%%r26\n", \ - DELTA, target_name, DELTA); \ - fprintf (FILE, "\n\t.EXIT\n\t.PROCEND\n"); \ -} - -/* NAME refers to the function's name. If we are placing each function into - its own section, we need to switch to the section for this function. Note - that the section name will have a "." prefix. */ -#define ASM_OUTPUT_FUNCTION_PREFIX(FILE, NAME) \ - { \ - char *name; \ - STRIP_NAME_ENCODING (name, NAME); \ - if (!TARGET_PORTABLE_RUNTIME && TARGET_GAS && in_section == in_text) \ - fputs ("\t.NSUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n", FILE); \ - else if (! TARGET_PORTABLE_RUNTIME && TARGET_GAS) \ - fprintf (FILE, \ - "\t.SUBSPA .%s\n", name); \ - } - -#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ - do { tree fntype = TREE_TYPE (TREE_TYPE (DECL)); \ - tree tree_type = TREE_TYPE (DECL); \ - tree parm; \ - int i; \ - if (TREE_PUBLIC (DECL) || TARGET_GAS) \ - { extern int current_function_varargs; \ - if (TREE_PUBLIC (DECL)) \ - { \ - fputs ("\t.EXPORT ", FILE); \ - assemble_name (FILE, NAME); \ - fputs (",ENTRY,PRIV_LEV=3", FILE); \ - } \ - else \ - { \ - fputs ("\t.PARAM ", FILE); \ - assemble_name (FILE, NAME); \ - } \ - if (TARGET_PORTABLE_RUNTIME) \ - { \ - fputs (",ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO,", FILE); \ - fputs ("RTNVAL=NO\n", FILE); \ - break; \ - } \ - for (parm = DECL_ARGUMENTS (DECL), i = 0; parm && i < 4; \ - parm = TREE_CHAIN (parm)) \ - { \ - if (TYPE_MODE (DECL_ARG_TYPE (parm)) == SFmode \ - && ! TARGET_SOFT_FLOAT) \ - fprintf (FILE, ",ARGW%d=FR", i++); \ - else if (TYPE_MODE (DECL_ARG_TYPE (parm)) == DFmode \ - && ! TARGET_SOFT_FLOAT) \ - { \ - if (i <= 2) \ - { \ - if (i == 1) i++; \ - ASM_DOUBLE_ARG_DESCRIPTORS (FILE, i++, i++); \ - } \ - else \ - break; \ - } \ - else \ - { \ - int arg_size = \ - FUNCTION_ARG_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)),\ - DECL_ARG_TYPE (parm)); \ - /* Passing structs by invisible reference uses \ - one general register. */ \ - if (arg_size > 2 \ - || TREE_ADDRESSABLE (DECL_ARG_TYPE (parm))) \ - arg_size = 1; \ - if (arg_size == 2 && i <= 2) \ - { \ - if (i == 1) i++; \ - fprintf (FILE, ",ARGW%d=GR", i++); \ - fprintf (FILE, ",ARGW%d=GR", i++); \ - } \ - else if (arg_size == 1) \ - fprintf (FILE, ",ARGW%d=GR", i++); \ - else \ - i += arg_size; \ - } \ - } \ - /* anonymous args */ \ - if ((TYPE_ARG_TYPES (tree_type) != 0 \ - && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (tree_type)))\ - != void_type_node)) \ - || current_function_varargs) \ - { \ - for (; i < 4; i++) \ - fprintf (FILE, ",ARGW%d=GR", i); \ - } \ - if (TYPE_MODE (fntype) == DFmode && ! TARGET_SOFT_FLOAT) \ - fputs (DFMODE_RETURN_STRING, FILE); \ - else if (TYPE_MODE (fntype) == SFmode && ! TARGET_SOFT_FLOAT) \ - fputs (SFMODE_RETURN_STRING, FILE); \ - else if (fntype != void_type_node) \ - fputs (",RTNVAL=GR", FILE); \ - fputs ("\n", FILE); \ - }} while (0) - -/* This macro generates the assembly code for function entry. - FILE is a stdio stream to output the code to. - SIZE is an int: how many units of temporary storage to allocate. - Refer to the array `regs_ever_live' to determine which registers - to save; `regs_ever_live[I]' is nonzero if register number I - is ever used in the function. This macro is responsible for - knowing which registers should not be saved even if used. */ - -/* On HP-PA, move-double insns between fpu and cpu need an 8-byte block - of memory. If any fpu reg is used in the function, we allocate - such a block here, at the bottom of the frame, just in case it's needed. - - If this function is a leaf procedure, then we may choose not - to do a "save" insn. The decision about whether or not - to do this is made in regclass.c. */ - -#define FUNCTION_PROLOGUE(FILE, SIZE) \ - output_function_prologue (FILE, SIZE) - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. - - Because HPUX _mcount is so different, we actually emit the - profiling code in function_prologue. This just stores LABELNO for - that. */ - -#define PROFILE_BEFORE_PROLOGUE -#define FUNCTION_PROFILER(FILE, LABELNO) \ -{ extern int hp_profile_labelno; hp_profile_labelno = (LABELNO);} - -/* 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. */ - -extern int may_call_alloca; -extern int current_function_pretend_args_size; - -#define EXIT_IGNORE_STACK \ - (get_frame_size () != 0 \ - || current_function_calls_alloca || current_function_outgoing_args_size) - - -/* This macro generates the assembly code for function exit, - on machines that need it. If FUNCTION_EPILOGUE is not defined - then individual return instructions are generated for each - return statement. Args are same as for FUNCTION_PROLOGUE. - - The function epilogue should not depend on the current stack pointer! - It should use the frame pointer only. This is mandatory because - of alloca; we also take advantage of it to omit stack adjustments - before returning. */ - -/* This declaration is needed due to traditional/ANSI - incompatibilities which cannot be #ifdefed away - because they occur inside of macros. Sigh. */ -extern union tree_node *current_function_decl; - -#define FUNCTION_EPILOGUE(FILE, SIZE) \ - output_function_epilogue (FILE, SIZE) - -/* Output assembler code for a block containing the constant parts - of a trampoline, leaving space for the variable parts.\ - - The trampoline sets the static chain pointer to STATIC_CHAIN_REGNUM - and then branches to the specified routine. - - This code template is copied from text segment to stack location - and then patched with INITIALIZE_TRAMPOLINE to contain - valid values, and then entered as a subroutine. - - It is best to keep this as small as possible to avoid having to - flush multiple lines in the cache. */ - -#define TRAMPOLINE_TEMPLATE(FILE) \ - { \ - fputs ("\tldw 36(0,%r22),%r21\n", FILE); \ - fputs ("\tbb,>=,n %r21,30,.+16\n", FILE); \ - fputs ("\tdepi 0,31,2,%r21\n", FILE); \ - fputs ("\tldw 4(0,%r21),%r19\n", FILE); \ - fputs ("\tldw 0(0,%r21),%r21\n", FILE); \ - fputs ("\tldsid (0,%r21),%r1\n", FILE); \ - fputs ("\tmtsp %r1,%sr0\n", FILE); \ - fputs ("\tbe 0(%sr0,%r21)\n", FILE); \ - fputs ("\tldw 40(0,%r22),%r29\n", FILE); \ - fputs ("\t.word 0\n", FILE); \ - fputs ("\t.word 0\n", FILE); \ - } - -/* Length in units of the trampoline for entering a nested function. - - Flush the cache entries corresponding to the first and last addresses - of the trampoline. This is necessary as the trampoline may cross two - cache lines. - - If the code part of the trampoline ever grows to > 32 bytes, then it - will become necessary to hack on the cacheflush pattern in pa.md. */ - -#define TRAMPOLINE_SIZE (11 * 4) - -/* 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. - - Move the function address to the trampoline template at offset 12. - Move the static chain value to trampoline template at offset 16. */ - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - rtx start_addr, end_addr; \ - \ - start_addr = memory_address (Pmode, plus_constant ((TRAMP), 36)); \ - emit_move_insn (gen_rtx_MEM (Pmode, start_addr), (FNADDR)); \ - start_addr = memory_address (Pmode, plus_constant ((TRAMP), 40)); \ - emit_move_insn (gen_rtx_MEM (Pmode, start_addr), (CXT)); \ - /* fdc and fic only use registers for the address to flush, \ - they do not accept integer displacements. */ \ - start_addr = force_reg (SImode, (TRAMP)); \ - end_addr = force_reg (SImode, plus_constant ((TRAMP), 32)); \ - emit_insn (gen_dcacheflush (start_addr, end_addr)); \ - end_addr = force_reg (SImode, plus_constant (start_addr, 32)); \ - emit_insn (gen_icacheflush (start_addr, end_addr, start_addr, \ - gen_reg_rtx (SImode), gen_reg_rtx (SImode)));\ -} - -/* Emit code for a call to builtin_saveregs. We must emit USE insns which - reference the 4 integer arg registers and 4 fp arg registers. - Ordinarily they are not call used registers, but they are for - _builtin_saveregs, so we must make this explicit. */ - -extern struct rtx_def *hppa_builtin_saveregs (); -#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) hppa_builtin_saveregs (ARGLIST) - - -/* Addressing modes, and classification of registers for them. */ -/* CYGNUS LOCAL PA8000/law */ -/* It is advisable to avoid autoincrement addressing modes on the PA8000 - series processors. This definition disables the most critical autoinc - usages (in loops). When the prologue/epilogue code is converted we - can probably disable autoinc entirely for the PA8000. */ -#define HAVE_POST_INCREMENT (pa_cpu == PROCESSOR_8000 ? flow2_completed : 1) -#define HAVE_POST_DECREMENT (pa_cpu == PROCESSOR_8000 ? flow2_completed : 1) - -#define HAVE_PRE_DECREMENT (pa_cpu == PROCESSOR_8000 ? flow2_completed : 1) -#define HAVE_PRE_INCREMENT (pa_cpu == PROCESSOR_8000 ? flow2_completed : 1) -/* END CYGNUS LOCAL */ - -/* 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_INDEX_P(REGNO) \ - ((REGNO) && ((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)) -#define REGNO_OK_FOR_BASE_P(REGNO) \ - ((REGNO) && ((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)) -#define REGNO_OK_FOR_FP_P(REGNO) \ - (FP_REGNO_P (REGNO) || FP_REGNO_P (reg_renumber[REGNO])) - -/* Now macros that check whether X is a register and also, - strictly, whether it is in a specified class. - - These macros are specific to the HP-PA, and may be used only - in code for printing assembler insns and in conditions for - define_optimization. */ - -/* 1 if X is an fp register. */ - -#define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X))) - -/* Maximum number of registers that can appear in a valid memory address. */ - -#define MAX_REGS_PER_ADDRESS 2 - -/* Recognize any constant value that is a valid address except - for symbolic addresses. We get better CSE by rejecting them - here and allowing hppa_legitimize_address to break them up. We - use most of the constants accepted by CONSTANT_P, except CONST_DOUBLE. */ - -#define CONSTANT_ADDRESS_P(X) \ - ((GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \ - || GET_CODE (X) == HIGH) \ - && (reload_in_progress || reload_completed || ! symbolic_expression_p (X))) - -/* Include all constant integers and constant doubles, but not - floating-point, except for floating-point zero. - - Reject LABEL_REFs if we're not using gas or the new HP assembler. */ -#ifdef NEW_HP_ASSEMBLER -#define LEGITIMATE_CONSTANT_P(X) \ - ((GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \ - || (X) == CONST0_RTX (GET_MODE (X))) \ - && !function_label_operand (X, VOIDmode)) -#else -#define LEGITIMATE_CONSTANT_P(X) \ - ((GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \ - || (X) == CONST0_RTX (GET_MODE (X))) \ - && (GET_CODE (X) != LABEL_REF || TARGET_GAS)\ - && !function_label_operand (X, VOIDmode)) -#endif - -/* Subroutine for EXTRA_CONSTRAINT. - - Return 1 iff OP is a pseudo which did not get a hard register and - we are running the reload pass. */ - -#define IS_RELOADING_PSEUDO_P(OP) \ - ((reload_in_progress \ - && GET_CODE (OP) == REG \ - && REGNO (OP) >= FIRST_PSEUDO_REGISTER \ - && reg_renumber [REGNO (OP)] < 0)) - -/* CYGNUS LOCAL PA8000/law */ -/* Optional extra constraints for this machine. Borrowed from sparc.h. - - For the HPPA, `Q' means that this is a memory operand but not a - symbolic memory operand. Note that an unassigned pseudo register - is such a memory operand. Needed because reload will generate - these things in insns and then not re-recognize the insns, causing - constrain_operands to fail. - - `R' is for certain scaled indexed addresses - - `S' is the constant 31. - - `T' is for fp loads and stores. */ -#define EXTRA_CONSTRAINT(OP, C) \ - ((C) == 'Q' ? \ - (IS_RELOADING_PSEUDO_P (OP) \ - || (GET_CODE (OP) == MEM \ - && (memory_address_p (GET_MODE (OP), XEXP (OP, 0))\ - || reload_in_progress) \ - && ! symbolic_memory_operand (OP, VOIDmode) \ - && !(GET_CODE (XEXP (OP, 0)) == PLUS \ - && (GET_CODE (XEXP (XEXP (OP, 0), 0)) == MULT\ - || GET_CODE (XEXP (XEXP (OP, 0), 1)) == MULT))))\ - : ((C) == 'R' ? \ - (GET_CODE (OP) == MEM \ - && GET_CODE (XEXP (OP, 0)) == PLUS \ - && (GET_CODE (XEXP (XEXP (OP, 0), 0)) == MULT \ - || GET_CODE (XEXP (XEXP (OP, 0), 1)) == MULT) \ - && (move_operand (OP, GET_MODE (OP)) \ - || memory_address_p (GET_MODE (OP), XEXP (OP, 0))\ - || reload_in_progress)) \ - : ((C) == 'T' ? \ - (GET_CODE (OP) == MEM \ - /* Using DFmode forces only short displacements \ - to be recognized as valid in reg+d addresses. */\ - && memory_address_p (DFmode, XEXP (OP, 0)) \ - && !(GET_CODE (XEXP (OP, 0)) == PLUS \ - && (GET_CODE (XEXP (XEXP (OP, 0), 0)) == MULT\ - || GET_CODE (XEXP (XEXP (OP, 0), 1)) == MULT))) \ - : ((C) == 'S' ? \ - (GET_CODE (OP) == CONST_INT && INTVAL (OP) == 31) : 0)))) -/* END CYGNUS LOCAL */ - - -/* 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) \ -(REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER)) -/* 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) \ -(REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER)) - -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) -/* 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)) - -#endif - -/* 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. - - On the HP-PA, the actual legitimate addresses must be - REG+REG, REG+(REG*SCALE) or REG+SMALLINT. - But we can treat a SYMBOL_REF as legitimate if it is part of this - function's constant-pool, because such addresses can actually - be output as REG+SMALLINT. - - Note we only allow 5 bit immediates for access to a constant address; - doing so avoids losing for loading/storing a FP register at an address - which will not fit in 5 bits. */ - -#define VAL_5_BITS_P(X) ((unsigned)(X) + 0x10 < 0x20) -#define INT_5_BITS(X) VAL_5_BITS_P (INTVAL (X)) - -#define VAL_U5_BITS_P(X) ((unsigned)(X) < 0x20) -#define INT_U5_BITS(X) VAL_U5_BITS_P (INTVAL (X)) - -#define VAL_11_BITS_P(X) ((unsigned)(X) + 0x400 < 0x800) -#define INT_11_BITS(X) VAL_11_BITS_P (INTVAL (X)) - -#define VAL_14_BITS_P(X) ((unsigned)(X) + 0x2000 < 0x4000) -#define INT_14_BITS(X) VAL_14_BITS_P (INTVAL (X)) - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ \ - if ((REG_P (X) && REG_OK_FOR_BASE_P (X)) \ - || ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_DEC \ - || GET_CODE (X) == PRE_INC || GET_CODE (X) == POST_INC) \ - && REG_P (XEXP (X, 0)) \ - && REG_OK_FOR_BASE_P (XEXP (X, 0)))) \ - goto ADDR; \ - else if (GET_CODE (X) == PLUS) \ - { \ - rtx base = 0, index = 0; \ - if (flag_pic && XEXP (X, 0) == pic_offset_table_rtx)\ - { \ - if (GET_CODE (XEXP (X, 1)) == REG \ - && REG_OK_FOR_BASE_P (XEXP (X, 1))) \ - goto ADDR; \ - else if (flag_pic == 1 \ - && GET_CODE (XEXP (X, 1)) == SYMBOL_REF)\ - goto ADDR; \ - } \ - else if (REG_P (XEXP (X, 0)) \ - && REG_OK_FOR_BASE_P (XEXP (X, 0))) \ - base = XEXP (X, 0), index = XEXP (X, 1); \ - else if (REG_P (XEXP (X, 1)) \ - && REG_OK_FOR_BASE_P (XEXP (X, 1))) \ - base = XEXP (X, 1), index = XEXP (X, 0); \ - if (base != 0) \ - if (GET_CODE (index) == CONST_INT \ - && ((INT_14_BITS (index) \ - && (TARGET_SOFT_FLOAT \ - /* CYGNUS LOCAL pa8000/law */ \ - || (TARGET_PARISC_2_0 \ - && ((MODE == SFmode \ - && (INTVAL (index) % 4) == 0)\ - || (MODE == DFmode \ - && (INTVAL (index) % 8) == 0)))\ - /* END CYGNUS LOCAL pa8000/law */ \ - || ((MODE) != SFmode && (MODE) != DFmode))) \ - || INT_5_BITS (index))) \ - goto ADDR; \ - if (! TARGET_SOFT_FLOAT \ - && ! TARGET_DISABLE_INDEXING \ - && base \ - && (mode == SFmode || mode == DFmode) \ - && GET_CODE (index) == MULT \ - && GET_CODE (XEXP (index, 0)) == REG \ - && REG_OK_FOR_BASE_P (XEXP (index, 0)) \ - && GET_CODE (XEXP (index, 1)) == CONST_INT \ - && INTVAL (XEXP (index, 1)) == (mode == SFmode ? 4 : 8))\ - goto ADDR; \ - } \ - else 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)) \ - && (TARGET_SOFT_FLOAT \ - || ((MODE) != SFmode \ - && (MODE) != DFmode))) \ - goto ADDR; \ - else if (GET_CODE (X) == LO_SUM \ - && GET_CODE (XEXP (X, 0)) == SUBREG \ - && GET_CODE (SUBREG_REG (XEXP (X, 0))) == REG\ - && REG_OK_FOR_BASE_P (SUBREG_REG (XEXP (X, 0)))\ - && CONSTANT_P (XEXP (X, 1)) \ - && (TARGET_SOFT_FLOAT \ - || ((MODE) != SFmode \ - && (MODE) != DFmode))) \ - goto ADDR; \ - else if (GET_CODE (X) == LABEL_REF \ - || (GET_CODE (X) == CONST_INT \ - && INT_5_BITS (X))) \ - goto ADDR; \ - /* Needed for -fPIC */ \ - else if (GET_CODE (X) == LO_SUM \ - && GET_CODE (XEXP (X, 0)) == REG \ - && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ - && GET_CODE (XEXP (X, 1)) == UNSPEC) \ - goto ADDR; \ -} - -/* Look for machine dependent ways to make the invalid address AD a - valid address. - - For the PA, transform: - - memory(X + <large int>) - - into: - - if (<large int> & mask) >= 16 - Y = (<large int> & ~mask) + mask + 1 Round up. - else - Y = (<large int> & ~mask) Round down. - Z = X + Y - memory (Z + (<large int> - Y)); - - This makes reload inheritance and reload_cse work better since Z - can be reused. - - There may be more opportunities to improve code with this hook. */ -#define LEGITIMIZE_RELOAD_ADDRESS(AD, MODE, OPNUM, TYPE, IND, WIN) \ -do { \ - int offset, newoffset, mask; \ - rtx new, temp = NULL_RTX; \ - mask = GET_MODE_CLASS (MODE) == MODE_FLOAT ? 0x1f : 0x3fff; \ - \ - /* CYGNUS LOCAL pa8000/law */ \ - mask = (GET_MODE_CLASS (MODE) == MODE_FLOAT \ - ? (TARGET_PARISC_2_0 ? 0x3fff : 0x1f) : 0x3fff); \ - /* END CYGNUS LOCAL */ \ - \ - if (optimize \ - && GET_CODE (AD) == PLUS) \ - temp = simplify_binary_operation (PLUS, Pmode, \ - XEXP (AD, 0), XEXP (AD, 1)); \ - \ - new = temp ? temp : AD; \ - \ - if (optimize \ - && GET_CODE (new) == PLUS \ - && GET_CODE (XEXP (new, 0)) == REG \ - && GET_CODE (XEXP (new, 1)) == CONST_INT) \ - { \ - offset = INTVAL (XEXP ((new), 1)); \ - \ - /* Choose rounding direction. Round up if we are >= halfway. */ \ - if ((offset & mask) >= ((mask + 1) / 2)) \ - newoffset = (offset & ~mask) + mask + 1; \ - else \ - newoffset = offset & ~mask; \ - \ - if (newoffset != 0 \ - && VAL_14_BITS_P (newoffset)) \ - { \ - \ - temp = gen_rtx_PLUS (Pmode, XEXP (new, 0), \ - GEN_INT (newoffset)); \ - AD = gen_rtx_PLUS (Pmode, temp, GEN_INT (offset - newoffset));\ - push_reload (XEXP (AD, 0), 0, &XEXP (AD, 0), 0, \ - BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, \ - (OPNUM), (TYPE)); \ - goto WIN; \ - } \ - } \ -} while (0) - - - - -/* Try machine-dependent ways of modifying an illegitimate address - to be legitimate. If we find one, return the new, valid address. - This macro is used in only one place: `memory_address' in explow.c. - - OLDX is the address as it was before break_out_memory_refs was called. - In some cases it is useful to look at this to decide what needs to be done. - - MODE and WIN are passed so that this macro can use - GO_IF_LEGITIMATE_ADDRESS. - - It is always safe for this macro to do nothing. It exists to recognize - opportunities to optimize the output. */ - -extern struct rtx_def *hppa_legitimize_address (); -#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ -{ rtx orig_x = (X); \ - (X) = hppa_legitimize_address (X, OLDX, MODE); \ - if ((X) != orig_x && memory_address_p (MODE, X)) \ - goto 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) \ - if (GET_CODE (ADDR) == PRE_DEC \ - || GET_CODE (ADDR) == POST_DEC \ - || GET_CODE (ADDR) == PRE_INC \ - || GET_CODE (ADDR) == POST_INC) \ - goto LABEL - -/* Define this macro if references to a symbol must be treated - differently depending on something about the variable or - function named by the symbol (such as what section it is in). - - The macro definition, if any, is executed immediately after the - rtl for DECL or other node is created. - The value of the rtl will be a `mem' whose address is a - `symbol_ref'. - - The usual thing for this macro to do is to a flag in the - `symbol_ref' (such as `SYMBOL_REF_FLAG') or to store a modified - name string in the `symbol_ref' (if one bit is not enough - information). - - On the HP-PA we use this to indicate if a symbol is in text or - data space. Also, function labels need special treatment. */ - -#define TEXT_SPACE_P(DECL)\ - (TREE_CODE (DECL) == FUNCTION_DECL \ - || (TREE_CODE (DECL) == VAR_DECL \ - && TREE_READONLY (DECL) && ! TREE_SIDE_EFFECTS (DECL) \ - && (! DECL_INITIAL (DECL) || ! reloc_needed (DECL_INITIAL (DECL))) \ - && !flag_pic) \ - || (TREE_CODE_CLASS (TREE_CODE (DECL)) == 'c' \ - && !(TREE_CODE (DECL) == STRING_CST && flag_writable_strings))) - -#define FUNCTION_NAME_P(NAME) \ -(*(NAME) == '@' || (*(NAME) == '*' && *((NAME) + 1) == '@')) - -#define ENCODE_SECTION_INFO(DECL)\ -do \ - { if (TEXT_SPACE_P (DECL)) \ - { rtx _rtl; \ - if (TREE_CODE (DECL) == FUNCTION_DECL \ - || TREE_CODE (DECL) == VAR_DECL) \ - _rtl = DECL_RTL (DECL); \ - else \ - _rtl = TREE_CST_RTL (DECL); \ - SYMBOL_REF_FLAG (XEXP (_rtl, 0)) = 1; \ - if (TREE_CODE (DECL) == FUNCTION_DECL) \ - hppa_encode_label (XEXP (DECL_RTL (DECL), 0), 0);\ - } \ - } \ -while (0) - -/* Store the user-specified part of SYMBOL_NAME in VAR. - This is sort of inverse to ENCODE_SECTION_INFO. */ - -#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \ - (VAR) = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*' ? \ - 1 + (SYMBOL_NAME)[1] == '@'\ - : (SYMBOL_NAME)[0] == '@')) - -/* On hpux10, the linker will give an error if we have a reference - in the read-only data section to a symbol defined in a shared - library. Therefore, expressions that might require a reloc can - not be placed in the read-only data section. */ -#define SELECT_SECTION(EXP,RELOC) \ - if (TREE_CODE (EXP) == VAR_DECL \ - && TREE_READONLY (EXP) \ - && !TREE_THIS_VOLATILE (EXP) \ - && DECL_INITIAL (EXP) \ - && (DECL_INITIAL (EXP) == error_mark_node \ - || TREE_CONSTANT (DECL_INITIAL (EXP))) \ - && !RELOC) \ - readonly_data_section (); \ - else if (TREE_CODE_CLASS (TREE_CODE (EXP)) == 'c' \ - && !(TREE_CODE (EXP) == STRING_CST && flag_writable_strings) \ - && !RELOC) \ - readonly_data_section (); \ - else \ - data_section (); - -/* Arghh. The hpux10 linker chokes if we have a reference to symbols - in a readonly data section when the symbol is defined in a shared - library. Since we can't know at compile time if a symbol will be - satisfied by a shared library or main program we put any symbolic - constant into the normal data section. */ -#define SELECT_RTX_SECTION(MODE,RTX) \ - if (symbolic_operand (RTX, MODE)) \ - data_section (); \ - else \ - readonly_data_section (); - -/* Specify the machine mode that this machine uses - for the index in the tablejump instruction. */ -#define CASE_VECTOR_MODE (TARGET_BIG_SWITCH ? TImode : DImode) - -/* Specify the tree operation to be used to convert reals to integers. */ -#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR - -/* This is the kind of divide that is easiest to do in the general case. */ -#define EASY_DIV_EXPR TRUNC_DIV_EXPR - -/* Define this as 1 if `char' should by default be signed; else as 0. */ -#define DEFAULT_SIGNED_CHAR 1 - -/* Max number of bytes we can move from memory to memory - in one reasonably fast instruction. */ -#define MOVE_MAX 8 - -/* Higher than the default as we prefer to use simple move insns - (better scheduling and delay slot filling) and because our - built-in block move is really a 2X unrolled loop. */ -#define MOVE_RATIO 4 - -/* Define if operations between registers always perform the operation - on the full register even if a narrower mode is specified. */ -#define WORD_REGISTER_OPERATIONS - -/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD - will either zero-extend or sign-extend. The value of this macro should - be the code that says which one of the two operations is implicitly - done, NIL if none. */ -#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND - -/* Nonzero if access to memory by bytes is slow and undesirable. */ -#define SLOW_BYTE_ACCESS 1 - -/* Do not break .stabs pseudos into continuations. - - This used to be zero (no max length), but big enums and such can - cause huge strings which killed gas. - - We also have to avoid lossage in dbxout.c -- it does not compute the - string size accurately, so we are real conservative here. */ -#define DBX_CONTIN_LENGTH 3000 - -/* 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 - -/* We assume that the store-condition-codes instructions store 0 for false - and some other value for true. This is the value stored for true. */ - -#define STORE_FLAG_VALUE 1 - -/* When a prototype says `char' or `short', really pass an `int'. */ -#define PROMOTE_PROTOTYPES - -/* 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 - -/* Add any extra modes needed to represent the condition code. - - HPPA floating comparisons produce condition codes. */ -#define EXTRA_CC_MODES CCFPmode - -/* Define the names for the modes specified above. */ -#define EXTRA_CC_NAMES "CCFP" - -/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, - return the mode to be used for the comparison. For floating-point, CCFPmode - should be used. CC_NOOVmode should be used when the first operand is a - PLUS, MINUS, or NEG. CCmode should be used when no special processing is - needed. */ -#define SELECT_CC_MODE(OP,X,Y) \ - (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CCFPmode : CCmode) \ - -/* 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 SImode - -/* Define this if addresses of constant functions - shouldn't be put through pseudo regs where they can be cse'd. - Desirable on machines where ordinary constants are expensive - but a CALL with constant address is cheap. */ -#define NO_FUNCTION_CSE - -/* Define this to be nonzero if shift instructions ignore all but the low-order - few bits. */ -#define SHIFT_COUNT_TRUNCATED 1 - -/* Use atexit for static constructors/destructors, instead of defining - our own exit function. */ -#define HAVE_ATEXIT - -/* Compute the cost of computing a constant rtl expression RTX - whose rtx-code is CODE. The body of this macro is a portion - of a switch statement. If the code is computed here, - return it with a return statement. Otherwise, break from the switch. */ - -#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ - case CONST_INT: \ - if (INTVAL (RTX) == 0) return 0; \ - if (INT_14_BITS (RTX)) return 1; \ - case HIGH: \ - return 2; \ - case CONST: \ - case LABEL_REF: \ - case SYMBOL_REF: \ - return 4; \ - case CONST_DOUBLE: \ - if ((RTX == CONST0_RTX (DFmode) || RTX == CONST0_RTX (SFmode)) \ - && OUTER_CODE != SET) \ - return 0; \ - else \ - return 8; - -#define ADDRESS_COST(RTX) \ - (GET_CODE (RTX) == REG ? 1 : hppa_address_cost (RTX)) - -/* Compute extra cost of moving data between one register class - and another. - - Make moves from SAR so expensive they should never happen. We used to - have 0xffff here, but that generates overflow in rare cases. - - Copies involving a FP register and a non-FP register are relatively - expensive because they must go through memory. - - Other copies are reasonably cheap. */ -#define REGISTER_MOVE_COST(CLASS1, CLASS2) \ - (CLASS1 == SHIFT_REGS ? 0x100 \ - : FP_REG_CLASS_P (CLASS1) && ! FP_REG_CLASS_P (CLASS2) ? 16 \ - : FP_REG_CLASS_P (CLASS2) && ! FP_REG_CLASS_P (CLASS1) ? 16 \ - : 2) - - -/* Provide the costs of a rtl expression. This is in the body of a - switch on CODE. The purpose for the cost of MULT is to encourage - `synth_mult' to find a synthetic multiply when reasonable. */ - -#define RTX_COSTS(X,CODE,OUTER_CODE) \ - case MULT: \ - if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \ - return COSTS_N_INSNS (3); \ - return (TARGET_SNAKE && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT) \ - ? COSTS_N_INSNS (8) : COSTS_N_INSNS (20); \ - case DIV: \ - if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \ - return COSTS_N_INSNS (14); \ - case UDIV: \ - case MOD: \ - case UMOD: \ - return COSTS_N_INSNS (60); \ - case PLUS: /* this includes shNadd insns */ \ - case MINUS: \ - if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \ - return COSTS_N_INSNS (3); \ - return COSTS_N_INSNS (1); \ - case ASHIFT: \ - case ASHIFTRT: \ - case LSHIFTRT: \ - return COSTS_N_INSNS (1); - -/* Adjust the cost of dependencies. */ - -#define ADJUST_COST(INSN,LINK,DEP,COST) \ - (COST) = pa_adjust_cost (INSN, LINK, DEP, COST) - -/* Adjust scheduling priorities. We use this to try and keep addil - and the next use of %r1 close together. */ -#define ADJUST_PRIORITY(PREV) \ - { \ - rtx set = single_set (PREV); \ - rtx src, dest; \ - if (set) \ - { \ - src = SET_SRC (set); \ - dest = SET_DEST (set); \ - if (GET_CODE (src) == LO_SUM \ - && symbolic_operand (XEXP (src, 1), VOIDmode) \ - && ! read_only_operand (XEXP (src, 1), VOIDmode)) \ - INSN_PRIORITY (PREV) >>= 3; \ - else if (GET_CODE (src) == MEM \ - && GET_CODE (XEXP (src, 0)) == LO_SUM \ - && symbolic_operand (XEXP (XEXP (src, 0), 1), VOIDmode)\ - && ! read_only_operand (XEXP (XEXP (src, 0), 1), VOIDmode))\ - INSN_PRIORITY (PREV) >>= 1; \ - else if (GET_CODE (dest) == MEM \ - && GET_CODE (XEXP (dest, 0)) == LO_SUM \ - && symbolic_operand (XEXP (XEXP (dest, 0), 1), VOIDmode)\ - && ! read_only_operand (XEXP (XEXP (dest, 0), 1), VOIDmode))\ - INSN_PRIORITY (PREV) >>= 3; \ - } \ - } - -/* Handling the special cases is going to get too complicated for a macro, - just call `pa_adjust_insn_length' to do the real work. */ -#define ADJUST_INSN_LENGTH(INSN, LENGTH) \ - LENGTH += pa_adjust_insn_length (INSN, LENGTH); - -/* Millicode insns are actually function calls with some special - constraints on arguments and register usage. - - Millicode calls always expect their arguments in the integer argument - registers, and always return their result in %r29 (ret1). They - are expected to clobber their arguments, %r1, %r29, and %r31 and - nothing else. - - These macros tell reorg that the references to arguments and - register clobbers for millicode calls do not appear to happen - until after the millicode call. This allows reorg to put insns - which set the argument registers into the delay slot of the millicode - call -- thus they act more like traditional CALL_INSNs. - - get_attr_type will try to recognize the given insn, so make sure to - filter out things it will not accept -- SEQUENCE, USE and CLOBBER insns - in particular. */ -#define INSN_SETS_ARE_DELAYED(X) (insn_sets_and_refs_are_delayed (X)) -#define INSN_REFERENCES_ARE_DELAYED(X) (insn_sets_and_refs_are_delayed (X)) - - -/* Control the assembler format that we output. */ - -/* Output at beginning of assembler file. */ - -#define ASM_FILE_START(FILE) \ -do { fputs ("\t.SPACE $PRIVATE$\n\ -\t.SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31\n\ -\t.SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82\n\ -\t.SPACE $TEXT$\n\ -\t.SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44\n\ -\t.SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n\ -\t.IMPORT $global$,DATA\n\ -\t.IMPORT $$dyncall,MILLICODE\n", FILE);\ - if (profile_flag)\ - fprintf (FILE, "\t.IMPORT _mcount, CODE\n");\ - if (write_symbols != NO_DEBUG) \ - output_file_directive ((FILE), main_input_filename); \ - } while (0) - -#define ASM_FILE_END(FILE) output_deferred_plabels (FILE) - -/* Output to assembler file text saying following lines - may contain character constants, extra white space, comments, etc. */ - -#define ASM_APP_ON "" - -/* Output to assembler file text saying following lines - no longer contain unusual constructs. */ - -#define ASM_APP_OFF "" - -/* We don't yet know how to identify GCC to HP-PA machines. */ -#define ASM_IDENTIFY_GCC(FILE) fputs ("; gcc_compiled.:\n", FILE) - -/* Output before code. */ - -/* Supposedly the assembler rejects the command if there is no tab! */ -#define TEXT_SECTION_ASM_OP "\t.SPACE $TEXT$\n\t.SUBSPA $CODE$\n" - -/* Output before read-only data. */ - -/* Supposedly the assembler rejects the command if there is no tab! */ -#define READONLY_DATA_ASM_OP "\t.SPACE $TEXT$\n\t.SUBSPA $LIT$\n" - -#define READONLY_DATA_SECTION readonly_data - -/* Output before writable data. */ - -/* Supposedly the assembler rejects the command if there is no tab! */ -#define DATA_SECTION_ASM_OP "\t.SPACE $PRIVATE$\n\t.SUBSPA $DATA$\n" - -/* Output before uninitialized data. */ - -#define BSS_SECTION_ASM_OP "\t.SPACE $PRIVATE$\n\t.SUBSPA $BSS$\n" - -/* Define the .bss section for ASM_OUTPUT_LOCAL to use. */ - -#ifndef CTORS_SECTION_FUNCTION -#define EXTRA_SECTIONS in_readonly_data -#define CTORS_SECTION_FUNCTION -#define DTORS_SECTION_FUNCTION -#else -#define EXTRA_SECTIONS in_readonly_data, in_ctors, in_dtors -#endif - -/* Switch into a generic section. - This is currently only used to support section attributes. - - We make the section read-only and executable for a function decl, - read-only for a const data decl, and writable for a non-const data decl. */ -#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ - if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \ - { \ - fputs ("\t.SPACE $TEXT$\n", FILE); \ - fprintf (FILE, \ - "\t.SUBSPA %s%s%s,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY,SORT=24\n",\ - TARGET_GAS ? "" : "$", NAME, TARGET_GAS ? "" : "$"); \ - } \ - else if (DECL && DECL_READONLY_SECTION (DECL, RELOC)) \ - { \ - fputs ("\t.SPACE $TEXT$\n", FILE); \ - fprintf (FILE, \ - "\t.SUBSPA %s%s%s,QUAD=0,ALIGN=8,ACCESS=44,SORT=16\n", \ - TARGET_GAS ? "" : "$", NAME, TARGET_GAS ? "" : "$"); \ - } \ - else \ - { \ - fputs ("\t.SPACE $PRIVATE$\n", FILE); \ - fprintf (FILE, \ - "\t.SUBSPA %s%s%s,QUAD=1,ALIGN=8,ACCESS=31,SORT=16\n", \ - TARGET_GAS ? "" : "$", NAME, TARGET_GAS ? "" : "$"); \ - } - -/* FIXME: HPUX ld generates incorrect GOT entries for "T" fixups - which reference data within the $TEXT$ space (for example constant - strings in the $LIT$ subspace). - - The assemblers (GAS and HP as) both have problems with handling - the difference of two symbols which is the other correct way to - reference constant data during PIC code generation. - - So, there's no way to reference constant data which is in the - $TEXT$ space during PIC generation. Instead place all constant - data into the $PRIVATE$ subspace (this reduces sharing, but it - works correctly). */ - -#define EXTRA_SECTION_FUNCTIONS \ -void \ -readonly_data () \ -{ \ - if (in_section != in_readonly_data) \ - { \ - if (flag_pic) \ - fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP); \ - else \ - fprintf (asm_out_file, "%s\n", READONLY_DATA_ASM_OP); \ - in_section = in_readonly_data; \ - } \ -} \ -CTORS_SECTION_FUNCTION \ -DTORS_SECTION_FUNCTION - - -/* 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", "%r3", "%r4", "%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", "%r30", "%r31", \ - "%fr4", "%fr4R", "%fr5", "%fr5R", "%fr6", "%fr6R", "%fr7", "%fr7R", \ - "%fr8", "%fr8R", "%fr9", "%fr9R", "%fr10", "%fr10R", "%fr11", "%fr11R", \ - "%fr12", "%fr12R", "%fr13", "%fr13R", "%fr14", "%fr14R", "%fr15", "%fr15R", \ - "%fr16", "%fr16R", "%fr17", "%fr17R", "%fr18", "%fr18R", "%fr19", "%fr19R", \ - "%fr20", "%fr20R", "%fr21", "%fr21R", "%fr22", "%fr22R", "%fr23", "%fr23R", \ - "%fr24", "%fr24R", "%fr25", "%fr25R", "%fr26", "%fr26R", "%fr27", "%fr27R", \ - "%fr28", "%fr28R", "%fr29", "%fr29R", "%fr30", "%fr30R", "%fr31", "%fr31R", \ - "SAR"} - -#define ADDITIONAL_REGISTER_NAMES \ -{{"%fr4L",32}, {"%fr5L",34}, {"%fr6L",36}, {"%fr7L",38}, \ - {"%fr8L",40}, {"%fr9L",42}, {"%fr10L",44}, {"%fr11L",46}, \ - {"%fr12L",48}, {"%fr13L",50}, {"%fr14L",52}, {"%fr15L",54}, \ - {"%fr16L",56}, {"%fr17L",58}, {"%fr18L",60}, {"%fr19L",62}, \ - {"%fr20L",64}, {"%fr21L",66}, {"%fr22L",68}, {"%fr23L",70}, \ - {"%fr24L",72}, {"%fr25L",74}, {"%fr26L",76}, {"%fr27L",78}, \ - {"%fr28L",80}, {"%fr29L",82}, {"%fr30L",84}, {"%fr31R",86}, \ - {"%cr11",88}} - -/* How to renumber registers for dbx and gdb. - - Registers 0 - 31 remain unchanged. - - Registers 32 - 87 are mapped to 72 - 127 - - Register 88 is mapped to 32. */ - -#define DBX_REGISTER_NUMBER(REGNO) \ - ((REGNO) <= 31 ? (REGNO) : \ - ((REGNO) > 31 && (REGNO) <= 87 ? (REGNO) + 40 : 32)) - -/* 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); \ - fputc ('\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. - - We call assemble_name, which in turn sets TREE_SYMBOL_REFERENCED. This - macro will restore the original value of TREE_SYMBOL_REFERENCED to avoid - placing useless function definitions in the output file. */ - -#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \ - do { int save_referenced; \ - save_referenced = TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL)); \ - fputs ("\t.IMPORT ", FILE); \ - assemble_name (FILE, NAME); \ - if (FUNCTION_NAME_P (NAME)) \ - fputs (",CODE\n", FILE); \ - else \ - fputs (",DATA\n", FILE); \ - TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL)) = save_referenced; \ - } while (0) - -/* The bogus HP assembler requires ALL external references to be - "imported", even library calls. They look a bit different, so - here's this macro. - - Also note not all libcall names are passed to ENCODE_SECTION_INFO - (__main for example). To make sure all libcall names have section - info recorded in them, we do it here. */ - -#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, RTL) \ - do { fputs ("\t.IMPORT ", FILE); \ - if (!function_label_operand (RTL, VOIDmode)) \ - hppa_encode_label (RTL, 1); \ - assemble_name (FILE, XSTR ((RTL), 0)); \ - fputs (",CODE\n", FILE); \ - } while (0) - -#define ASM_GLOBALIZE_LABEL(FILE, NAME) \ - do { \ - /* We only handle DATA objects here, functions are globalized in \ - ASM_DECLARE_FUNCTION_NAME. */ \ - if (! FUNCTION_NAME_P (NAME)) \ - { \ - fputs ("\t.EXPORT ", FILE); \ - assemble_name (FILE, NAME); \ - fputs (",DATA\n", FILE); \ - } \ - } while (0) - -/* This is how to output a reference to a user-level label named NAME. - `assemble_name' uses this. */ - -#define ASM_OUTPUT_LABELREF(FILE,NAME) \ - fprintf ((FILE), "%s", (NAME) + (FUNCTION_NAME_P (NAME) ? 1 : 0)) - -/* This is how to output an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. */ - -#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ - {fprintf (FILE, "%c$%s%04d\n", (PREFIX)[0], (PREFIX) + 1, NUM);} - -/* This is how to store into the string LABEL - the symbol_ref name of an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. - This is suitable for output with `assemble_name'. */ - -#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf (LABEL, "*%c$%s%04d", (PREFIX)[0], (PREFIX) + 1, NUM) - -/* This is how to output an assembler line defining a `double' constant. */ - -#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ - do { long l[2]; \ - REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \ - fprintf (FILE, "\t.word 0x%lx\n\t.word 0x%lx\n", l[0], l[1]); \ - } while (0) - -/* This is how to output an assembler line defining a `float' constant. */ - -#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ - do { long l; \ - REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \ - fprintf (FILE, "\t.word 0x%lx\n", l); \ - } while (0) - -/* This is how to output an assembler line defining an `int' constant. - - This is made more complicated by the fact that functions must be - prefixed by a P% as well as code label references for the exception - table -- otherwise the linker chokes. */ - -#define ASM_OUTPUT_INT(FILE,VALUE) \ -{ fputs ("\t.word ", FILE); \ - if (function_label_operand (VALUE, VOIDmode) \ - && !TARGET_PORTABLE_RUNTIME) \ - fputs ("P%", FILE); \ - output_addr_const (FILE, (VALUE)); \ - fputs ("\n", FILE);} - -/* Likewise for `short' and `char' constants. */ - -#define ASM_OUTPUT_SHORT(FILE,VALUE) \ -( fputs ("\t.half ", FILE), \ - output_addr_const (FILE, (VALUE)), \ - fputs ("\n", FILE)) - -#define ASM_OUTPUT_CHAR(FILE,VALUE) \ -( fputs ("\t.byte ", FILE), \ - output_addr_const (FILE, (VALUE)), \ - fputs ("\n", FILE)) - -/* 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 ASM_OUTPUT_ASCII(FILE, P, SIZE) \ - output_ascii ((FILE), (P), (SIZE)) - -#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. - Note that this method makes filling these branch delay slots - impossible. */ - -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - if (TARGET_BIG_SWITCH) \ - fprintf (FILE, "\tstw %%r1,-16(%%r30)\n\tldil LR'L$%04d,%%r1\n\tbe RR'L$%04d(%%sr4,%%r1)\n\tldw -16(%%r30),%%r1\n", VALUE, VALUE); \ - else \ - fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE) - -/* Jump tables are executable code and live in the TEXT section on the PA. */ -#define JUMP_TABLES_IN_TEXT_SECTION 1 - -/* This is how to output an element of a case-vector that is relative. - This must be defined correctly as it is used when generating PIC code. - - I believe it safe to use the same definition as ASM_OUTPUT_ADDR_VEC_ELT - on the PA since ASM_OUTPUT_ADDR_VEC_ELT uses pc-relative jump instructions - rather than a table of absolute addresses. */ - -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - if (TARGET_BIG_SWITCH) \ - fprintf (FILE, "\tstw %%r1,-16(%%r30)\n\tldw T'L$%04d(%%r19),%%r1\n\tbv 0(%%r1)\n\tldw -16(%%r30),%%r1\n", VALUE); \ - else \ - fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE) - -/* This is how to output an assembler line - that says to advance the location counter - to a multiple of 2**LOG bytes. */ - -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ - fprintf (FILE, "\t.align %d\n", (1<<(LOG))) - -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\t.blockz %d\n", (SIZE)) - -/* This says how to output an assembler line to define a global common symbol - with size SIZE (in bytes) and alignment ALIGN (in bits). */ - -#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGNED) \ -{ bss_section (); \ - assemble_name ((FILE), (NAME)); \ - fputs ("\t.comm ", (FILE)); \ - fprintf ((FILE), "%d\n", MAX ((SIZE), ((ALIGNED) / BITS_PER_UNIT)));} - -/* This says how to output an assembler line to define a local common symbol - with size SIZE (in bytes) and alignment ALIGN (in bits). */ - -#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGNED) \ -{ bss_section (); \ - fprintf ((FILE), "\t.align %d\n", ((ALIGNED) / BITS_PER_UNIT)); \ - assemble_name ((FILE), (NAME)); \ - fprintf ((FILE), "\n\t.block %d\n", (SIZE));} - -/* 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)) + 12), \ - sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO))) - -/* Define the parentheses used to group arithmetic operations - in assembler code. */ - -#define ASM_OPEN_PAREN "(" -#define ASM_CLOSE_PAREN ")" - -/* All HP assemblers use "!" to separate logical lines. */ -#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == '!') - -/* 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 - -#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \ - ((CHAR) == '@' || (CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^') - -/* Print operand X (an rtx) in assembler syntax to file FILE. - CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. - For `%' followed by punctuation, CODE is the punctuation and X is null. - - On the HP-PA, the CODE can be `r', meaning this is a register-only operand - and an immediate zero should be represented as `r0'. - - Several % codes are defined: - O an operation - C compare conditions - N extract conditions - M modifier to handle preincrement addressing for memory refs. - F modifier to handle preincrement addressing for fp memory refs */ - -#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE) - - -/* Print a memory address as an operand to reference that memory location. */ - -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ -{ register rtx addr = ADDR; \ - register rtx base; \ - int offset; \ - switch (GET_CODE (addr)) \ - { \ - case REG: \ - fprintf (FILE, "0(0,%s)", reg_names [REGNO (addr)]); \ - break; \ - case PLUS: \ - if (GET_CODE (XEXP (addr, 0)) == CONST_INT) \ - offset = INTVAL (XEXP (addr, 0)), base = XEXP (addr, 1); \ - else if (GET_CODE (XEXP (addr, 1)) == CONST_INT) \ - offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0); \ - else \ - abort (); \ - fprintf (FILE, "%d(0,%s)", offset, reg_names [REGNO (base)]); \ - break; \ - case LO_SUM: \ - if (!symbolic_operand (XEXP (addr, 1))) \ - fputs ("R'", FILE); \ - else if (flag_pic == 0) \ - fputs ("RR'", FILE); \ - else if (flag_pic == 1) \ - abort (); \ - else if (flag_pic == 2) \ - fputs ("RT'", FILE); \ - output_global_address (FILE, XEXP (addr, 1), 0); \ - fputs ("(", FILE); \ - output_operand (XEXP (addr, 0), 0); \ - fputs (")", FILE); \ - break; \ - case CONST_INT: \ - fprintf (FILE, "%d(0,0)", INTVAL (addr)); \ - break; \ - default: \ - output_addr_const (FILE, addr); \ - }} - - -/* Define functions in pa.c and used in insn-output.c. */ - -extern char *output_and (); -extern char *output_ior (); -extern char *output_move_double (); -extern char *output_fp_move_double (); -extern char *output_block_move (); -extern char *output_cbranch (); -extern char *output_bb (); -extern char *output_bvb (); -extern char *output_dbra (); -extern char *output_movb (); -extern char *output_parallel_movb (); -extern char *output_parallel_addb (); -extern char *output_return (); -extern char *output_call (); -extern char *output_millicode_call (); -extern char *output_mul_insn (); -extern char *output_div_insn (); -extern char *output_mod_insn (); -extern char *singlemove_string (); -extern void output_arg_descriptor (); -extern void output_deferred_plabels (); -extern void override_options (); -extern void output_ascii (); -extern void output_function_prologue (); -extern void output_function_epilogue (); -extern void output_global_address (); -extern void print_operand (); -extern struct rtx_def *legitimize_pic_address (); -extern struct rtx_def *gen_cmp_fp (); -extern void hppa_encode_label (); -extern int arith11_operand (); -extern int symbolic_expression_p (); -extern int reloc_needed (); -extern int compute_frame_size (); -extern int hppa_address_cost (); -extern int and_mask_p (); -extern int symbolic_memory_operand (); -extern int pa_adjust_cost (); -extern int pa_adjust_insn_length (); -extern int int11_operand (); -extern int reg_or_cint_move_operand (); -extern int arith5_operand (); -extern int uint5_operand (); -extern int pic_label_operand (); -extern int plus_xor_ior_operator (); -extern int basereg_operand (); -extern int shadd_operand (); -extern int arith_operand (); -extern int read_only_operand (); -extern int move_operand (); -extern int and_operand (); -extern int ior_operand (); -extern int arith32_operand (); -extern int uint32_operand (); -extern int reg_or_nonsymb_mem_operand (); -extern int reg_or_0_operand (); -extern int reg_or_0_or_nonsymb_mem_operand (); -extern int pre_cint_operand (); -extern int post_cint_operand (); -extern int div_operand (); -extern int int5_operand (); -extern int movb_comparison_operator (); -extern int ireg_or_int5_operand (); -extern int fmpyaddoperands (); -extern int fmpysuboperands (); -extern int call_operand_address (); -extern int cint_ok_for_move (); -extern int ior_operand (); -extern void emit_bcond_fp (); -extern int emit_move_sequence (); -extern int emit_hpdiv_const (); -extern void hppa_expand_prologue (); -extern void hppa_expand_epilogue (); -extern int hppa_can_use_return_insn_p (); -extern int is_function_label_plus_const (); -extern int jump_in_call_delay (); -extern enum reg_class secondary_reload_class (); -extern int insn_sets_and_refs_are_delayed (); - -/* Declare functions defined in pa.c and used in templates. */ - -extern struct rtx_def *return_addr_rtx (); - -/* We want __gcc_plt_call to appear in every program built by - gcc, so we make a reference to it out of __main. - We use the asm statement to fool the optimizer into not - removing the dead (but important) initialization of - REFERENCE. */ - -#define DO_GLOBAL_DTORS_BODY \ -do { \ - extern void __gcc_plt_call (); \ - void (*reference)() = &__gcc_plt_call; \ - func_ptr *p; \ - __asm__ ("" : : "r" (reference)); \ - for (p = __DTOR_LIST__ + 1; *p; ) \ - (*p++) (); \ -} while (0) - -/* Find the return address associated with the frame given by - FRAMEADDR. */ -#define RETURN_ADDR_RTX(COUNT, FRAMEADDR) \ - (return_addr_rtx (COUNT, FRAMEADDR)) - -/* Used to mask out junk bits from the return address, such as - processor state, interrupt status, condition codes and the like. */ -#define MASK_RETURN_ADDR \ - /* The privilege level is in the two low order bits, mask em out \ - of the return address. */ \ - (GEN_INT (0xfffffffc)) - -/* The number of Pmode words for the setjmp buffer. */ -#define JMP_BUF_SIZE 50 diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md deleted file mode 100755 index 174bbd7..0000000 --- a/gcc/config/pa/pa.md +++ /dev/null @@ -1,5729 +0,0 @@ -;;- Machine description for HP PA-RISC architecture for GNU C compiler -;; Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc. -;; Contributed by the Center for Software Science at the University -;; of Utah. - -;; 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. - -;; This gcc Version 2 machine description is inspired by sparc.md and -;; mips.md. - -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. - -;; Insn type. Used to default other attribute values. - -;; type "unary" insns have one input operand (1) and one output operand (0) -;; type "binary" insns have two input operands (1,2) and one output (0) - -(define_attr "type" - "move,unary,binary,shift,nullshift,compare,load,store,uncond_branch,branch,cbranch,fbranch,call,dyncall,fpload,fpstore,fpalu,fpcc,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,milli,parallel_branch" - (const_string "binary")) - -(define_attr "pa_combine_type" - "fmpy,faddsub,uncond_branch,addmove,none" - (const_string "none")) - -;; Processor type (for scheduling, not code generation) -- this attribute -;; must exactly match the processor_type enumeration in pa.h. -;; -;; FIXME: Add 800 scheduling for completeness? - -;; CYGNUS LOCAL PA8000/law -(define_attr "cpu" "700,7100,7100LC,7200,8000" (const (symbol_ref "pa_cpu_attr"))) -;; END CYGNUS LOCAL - -;; Length (in # of insns). -(define_attr "length" "" - (cond [(eq_attr "type" "load,fpload") - (if_then_else (match_operand 1 "symbolic_memory_operand" "") - (const_int 8) (const_int 4)) - - (eq_attr "type" "store,fpstore") - (if_then_else (match_operand 0 "symbolic_memory_operand" "") - (const_int 8) (const_int 4)) - - (eq_attr "type" "binary,shift,nullshift") - (if_then_else (match_operand 2 "arith_operand" "") - (const_int 4) (const_int 12)) - - (eq_attr "type" "move,unary,shift,nullshift") - (if_then_else (match_operand 1 "arith_operand" "") - (const_int 4) (const_int 8))] - - (const_int 4))) - -(define_asm_attributes - [(set_attr "length" "4") - (set_attr "type" "multi")]) - -;; Attributes for instruction and branch scheduling - -;; For conditional branches. -(define_attr "in_branch_delay" "false,true" - (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,parallel_branch") - (eq_attr "length" "4")) - (const_string "true") - (const_string "false"))) - -;; Disallow instructions which use the FPU since they will tie up the FPU -;; even if the instruction is nullified. -(define_attr "in_nullified_branch_delay" "false,true" - (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,parallel_branch") - (eq_attr "length" "4")) - (const_string "true") - (const_string "false"))) - -;; For calls and millicode calls. Allow unconditional branches in the -;; delay slot. -(define_attr "in_call_delay" "false,true" - (cond [(and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,parallel_branch") - (eq_attr "length" "4")) - (const_string "true") - (eq_attr "type" "uncond_branch") - (if_then_else (ne (symbol_ref "TARGET_JUMP_IN_DELAY") - (const_int 0)) - (const_string "true") - (const_string "false"))] - (const_string "false"))) - - -;; Call delay slot description. -(define_delay (eq_attr "type" "call") - [(eq_attr "in_call_delay" "true") (nil) (nil)]) - -;; millicode call delay slot description. Note it disallows delay slot -;; when TARGET_PORTABLE_RUNTIME is true. -(define_delay (eq_attr "type" "milli") - [(and (eq_attr "in_call_delay" "true") - (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))) - (nil) (nil)]) - -;; Return and other similar instructions. -(define_delay (eq_attr "type" "branch,parallel_branch") - [(eq_attr "in_branch_delay" "true") (nil) (nil)]) - -;; Floating point conditional branch delay slot description and -(define_delay (eq_attr "type" "fbranch") - [(eq_attr "in_branch_delay" "true") - (eq_attr "in_nullified_branch_delay" "true") - (nil)]) - -;; Integer conditional branch delay slot description. -;; Nullification of conditional branches on the PA is dependent on the -;; direction of the branch. Forward branches nullify true and -;; backward branches nullify false. If the direction is unknown -;; then nullification is not allowed. -(define_delay (eq_attr "type" "cbranch") - [(eq_attr "in_branch_delay" "true") - (and (eq_attr "in_nullified_branch_delay" "true") - (attr_flag "forward")) - (and (eq_attr "in_nullified_branch_delay" "true") - (attr_flag "backward"))]) - -(define_delay (and (eq_attr "type" "uncond_branch") - (eq (symbol_ref "following_call (insn)") - (const_int 0))) - [(eq_attr "in_branch_delay" "true") (nil) (nil)]) - -;; Function units of the HPPA. The following data is for the 700 CPUs -;; (Mustang CPU + Timex FPU aka PA-89) because that's what I have the docs for. -;; Scheduling instructions for PA-83 machines according to the Snake -;; constraints shouldn't hurt. - -;; (define_function_unit {name} {num-units} {n-users} {test} -;; {ready-delay} {issue-delay} [{conflict-list}]) - -;; The integer ALU. -;; (Noted only for documentation; units that take one cycle do not need to -;; be specified.) - -;; (define_function_unit "alu" 1 0 -;; (and (eq_attr "type" "unary,shift,nullshift,binary,move,address") -;; (eq_attr "cpu" "700")) -;; 1 0) - - -;; Memory. Disregarding Cache misses, the Mustang memory times are: -;; load: 2, fpload: 3 -;; store, fpstore: 3, no D-cache operations should be scheduled. - -(define_function_unit "pa700memory" 1 0 - (and (eq_attr "type" "load,fpload") - (eq_attr "cpu" "700")) 2 0) -(define_function_unit "pa700memory" 1 0 - (and (eq_attr "type" "store,fpstore") - (eq_attr "cpu" "700")) 3 3) - -;; The Timex (aka 700) has two floating-point units: ALU, and MUL/DIV/SQRT. -;; Timings: -;; Instruction Time Unit Minimum Distance (unit contention) -;; fcpy 3 ALU 2 -;; fabs 3 ALU 2 -;; fadd 3 ALU 2 -;; fsub 3 ALU 2 -;; fcmp 3 ALU 2 -;; fcnv 3 ALU 2 -;; fmpyadd 3 ALU,MPY 2 -;; fmpysub 3 ALU,MPY 2 -;; fmpycfxt 3 ALU,MPY 2 -;; fmpy 3 MPY 2 -;; fmpyi 3 MPY 2 -;; fdiv,sgl 10 MPY 10 -;; fdiv,dbl 12 MPY 12 -;; fsqrt,sgl 14 MPY 14 -;; fsqrt,dbl 18 MPY 18 - -(define_function_unit "pa700fp_alu" 1 0 - (and (eq_attr "type" "fpcc") - (eq_attr "cpu" "700")) 4 2) -(define_function_unit "pa700fp_alu" 1 0 - (and (eq_attr "type" "fpalu") - (eq_attr "cpu" "700")) 3 2) -(define_function_unit "pa700fp_mpy" 1 0 - (and (eq_attr "type" "fpmulsgl,fpmuldbl") - (eq_attr "cpu" "700")) 3 2) -(define_function_unit "pa700fp_mpy" 1 0 - (and (eq_attr "type" "fpdivsgl") - (eq_attr "cpu" "700")) 10 10) -(define_function_unit "pa700fp_mpy" 1 0 - (and (eq_attr "type" "fpdivdbl") - (eq_attr "cpu" "700")) 12 12) -(define_function_unit "pa700fp_mpy" 1 0 - (and (eq_attr "type" "fpsqrtsgl") - (eq_attr "cpu" "700")) 14 14) -(define_function_unit "pa700fp_mpy" 1 0 - (and (eq_attr "type" "fpsqrtdbl") - (eq_attr "cpu" "700")) 18 18) - -;; Function units for the 7100 and 7150. The 7100/7150 can dual-issue -;; floating point computations with non-floating point computations (fp loads -;; and stores are not fp computations). -;; - -;; Memory. Disregarding Cache misses, memory loads take two cycles; stores also -;; take two cycles, during which no Dcache operations should be scheduled. -;; Any special cases are handled in pa_adjust_cost. The 7100, 7150 and 7100LC -;; all have the same memory characteristics if one disregards cache misses. -(define_function_unit "pa7100memory" 1 0 - (and (eq_attr "type" "load,fpload") - (eq_attr "cpu" "7100,7100LC")) 2 0) -(define_function_unit "pa7100memory" 1 0 - (and (eq_attr "type" "store,fpstore") - (eq_attr "cpu" "7100,7100LC")) 2 2) - -;; The 7100/7150 has three floating-point units: ALU, MUL, and DIV. -;; Timings: -;; Instruction Time Unit Minimum Distance (unit contention) -;; fcpy 2 ALU 1 -;; fabs 2 ALU 1 -;; fadd 2 ALU 1 -;; fsub 2 ALU 1 -;; fcmp 2 ALU 1 -;; fcnv 2 ALU 1 -;; fmpyadd 2 ALU,MPY 1 -;; fmpysub 2 ALU,MPY 1 -;; fmpycfxt 2 ALU,MPY 1 -;; fmpy 2 MPY 1 -;; fmpyi 2 MPY 1 -;; fdiv,sgl 8 DIV 8 -;; fdiv,dbl 15 DIV 15 -;; fsqrt,sgl 8 DIV 8 -;; fsqrt,dbl 15 DIV 15 - -(define_function_unit "pa7100fp_alu" 1 0 - (and (eq_attr "type" "fpcc,fpalu") - (eq_attr "cpu" "7100")) 2 1) -(define_function_unit "pa7100fp_mpy" 1 0 - (and (eq_attr "type" "fpmulsgl,fpmuldbl") - (eq_attr "cpu" "7100")) 2 1) -(define_function_unit "pa7100fp_div" 1 0 - (and (eq_attr "type" "fpdivsgl,fpsqrtsgl") - (eq_attr "cpu" "7100")) 8 8) -(define_function_unit "pa7100fp_div" 1 0 - (and (eq_attr "type" "fpdivdbl,fpsqrtdbl") - (eq_attr "cpu" "7100")) 15 15) - -;; To encourage dual issue we define function units corresponding to -;; the instructions which can be dual issued. This is a rather crude -;; approximation, the "pa7100nonflop" test in particular could be refined. -(define_function_unit "pa7100flop" 1 1 - (and - (eq_attr "type" "fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpsqrtsgl,fpdivdbl,fpsqrtdbl") - (eq_attr "cpu" "7100")) 1 1) - -(define_function_unit "pa7100nonflop" 1 1 - (and - (eq_attr "type" "!fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpsqrtsgl,fpdivdbl,fpsqrtdbl") - (eq_attr "cpu" "7100")) 1 1) - - -;; Memory subsystem works just like 7100/7150 (except for cache miss times which -;; we don't model here). - -;; The 7100LC has three floating-point units: ALU, MUL, and DIV. -;; Note divides and sqrt flops lock the cpu until the flop is -;; finished. fmpy and xmpyu (fmpyi) lock the cpu for one cycle. -;; There's no way to avoid the penalty. -;; Timings: -;; Instruction Time Unit Minimum Distance (unit contention) -;; fcpy 2 ALU 1 -;; fabs 2 ALU 1 -;; fadd 2 ALU 1 -;; fsub 2 ALU 1 -;; fcmp 2 ALU 1 -;; fcnv 2 ALU 1 -;; fmpyadd,sgl 2 ALU,MPY 1 -;; fmpyadd,dbl 3 ALU,MPY 2 -;; fmpysub,sgl 2 ALU,MPY 1 -;; fmpysub,dbl 3 ALU,MPY 2 -;; fmpycfxt,sgl 2 ALU,MPY 1 -;; fmpycfxt,dbl 3 ALU,MPY 2 -;; fmpy,sgl 2 MPY 1 -;; fmpy,dbl 3 MPY 2 -;; fmpyi 3 MPY 2 -;; fdiv,sgl 8 DIV 8 -;; fdiv,dbl 15 DIV 15 -;; fsqrt,sgl 8 DIV 8 -;; fsqrt,dbl 15 DIV 15 - -(define_function_unit "pa7100LCfp_alu" 1 0 - (and (eq_attr "type" "fpcc,fpalu") - (eq_attr "cpu" "7100LC,7200")) 2 1) -(define_function_unit "pa7100LCfp_mpy" 1 0 - (and (eq_attr "type" "fpmulsgl") - (eq_attr "cpu" "7100LC,7200")) 2 1) -(define_function_unit "pa7100LCfp_mpy" 1 0 - (and (eq_attr "type" "fpmuldbl") - (eq_attr "cpu" "7100LC,7200")) 3 2) -(define_function_unit "pa7100LCfp_div" 1 0 - (and (eq_attr "type" "fpdivsgl,fpsqrtsgl") - (eq_attr "cpu" "7100LC,7200")) 8 8) -(define_function_unit "pa7100LCfp_div" 1 0 - (and (eq_attr "type" "fpdivdbl,fpsqrtdbl") - (eq_attr "cpu" "7100LC,7200")) 15 15) - -;; Define the various functional units for dual-issue. - -;; There's only one floating point unit. -(define_function_unit "pa7100LCflop" 1 1 - (and - (eq_attr "type" "fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpsqrtsgl,fpdivdbl,fpsqrtdbl") - (eq_attr "cpu" "7100LC,7200")) 1 1) - -;; Shifts and memory ops actually execute in one of the integer -;; ALUs, but we can't really model that. -(define_function_unit "pa7100LCshiftmem" 1 1 - (and - (eq_attr "type" "shift,nullshift,load,fpload,store,fpstore") - (eq_attr "cpu" "7100LC,7200")) 1 1) - -;; We have two basic ALUs. -(define_function_unit "pa7100LCalu" 2 2 - (and - (eq_attr "type" "!fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpsqrtsgl,fpdivdbl,fpsqrtdbl,load,fpload,store,fpstore,shift,nullshift") - (eq_attr "cpu" "7100LC,7200")) 1 1) - -;; I don't have complete information on the PA7200; however, most of -;; what I've heard makes it look like a 7100LC without the store-store -;; penalty. So that's how we'll model it. - -;; Memory. Disregarding Cache misses, memory loads and stores take -;; two cycles. Any special cases are handled in pa_adjust_cost. -(define_function_unit "pa7200memory" 1 0 - (and (eq_attr "type" "load,fpload,store,fpstore") - (eq_attr "cpu" "7200")) 2 0) - -;; I don't have detailed information on the PA7200 FP pipeline, so I -;; treat it just like the 7100LC pipeline. -;; Similarly for the multi-issue fake units. - -;; CYGNUS LOCAL PA8000/law -;; -;; Scheduling for the PA8000 is somewhat different than scheduling for a -;; traditional architecture. -;; -;; The PA8000 has a large (56) entry reorder buffer that is split between -;; memory and non-memory operations. -;; -;; The PA800 can issue two memory and two non-memory operations per cycle to -;; the function units. Similarly, the PA8000 can retire two memory and two -;; non-memory operations per cycle. -;; -;; Given the large reorder buffer, the processor can hide most latencies. -;; According to HP, they've got the best results by scheduling for retirement -;; bandwidth with limited latency scheduling for floating point operations. -;; Latency for integer operations and memory references is ignored. -;; -;; We claim floating point operations have a 2 cycle latency and are -;; fully pipelined, except for div and sqrt which are not pipelined. -;; -;; It is not necessary to define the shifter and integer alu units. -;; -;; These first two define_unit_unit descriptions model retirement from -;; the reorder buffer. -(define_function_unit "pa8000lsu" 2 2 - (and - (eq_attr "type" "load,fpload,store,fpstore") - (eq_attr "cpu" "8000")) 1 0) - -(define_function_unit "pa8000alu" 2 2 - (and - (eq_attr "type" "!load,fpload,store,fpstore") - (eq_attr "cpu" "8000")) 1 0) - -;; Claim floating point ops have a 2 cycle latency, including div and -;; sqrt, but div and sqrt are not pipelined and issue to different units. -(define_function_unit "pa8000fmac" 2 0 - (and - (eq_attr "type" "fpcc,fpalu,fpmulsgl,fpmuldbl") - (eq_attr "cpu" "8000")) 2 0) - -(define_function_unit "pa8000fdiv" 2 2 - (and - (eq_attr "type" "fpdivsgl,fpsqrtsgl") - (eq_attr "cpu" "8000")) 17 17) - -(define_function_unit "pa8000fdiv" 2 2 - (and - (eq_attr "type" "fpdivdbl,fpsqrtdbl") - (eq_attr "cpu" "8000")) 31 31) -;; END CYGNUS LOCAL - -;; Compare instructions. -;; This controls RTL generation and register allocation. - -;; We generate RTL for comparisons and branches by having the cmpxx -;; patterns store away the operands. Then, the scc and bcc patterns -;; emit RTL for both the compare and the branch. -;; - -(define_expand "cmpsi" - [(set (reg:CC 0) - (compare:CC (match_operand:SI 0 "reg_or_0_operand" "") - (match_operand:SI 1 "arith5_operand" "")))] - "" - " -{ - hppa_compare_op0 = operands[0]; - hppa_compare_op1 = operands[1]; - hppa_branch_type = CMP_SI; - DONE; -}") - -(define_expand "cmpsf" - [(set (reg:CCFP 0) - (compare:CCFP (match_operand:SF 0 "reg_or_0_operand" "") - (match_operand:SF 1 "reg_or_0_operand" "")))] - "! TARGET_SOFT_FLOAT" - " -{ - hppa_compare_op0 = operands[0]; - hppa_compare_op1 = operands[1]; - hppa_branch_type = CMP_SF; - DONE; -}") - -(define_expand "cmpdf" - [(set (reg:CCFP 0) - (compare:CCFP (match_operand:DF 0 "reg_or_0_operand" "") - (match_operand:DF 1 "reg_or_0_operand" "")))] - "! TARGET_SOFT_FLOAT" - " -{ - hppa_compare_op0 = operands[0]; - hppa_compare_op1 = operands[1]; - hppa_branch_type = CMP_DF; - DONE; -}") - -(define_insn "" - [(set (reg:CCFP 0) - (match_operator:CCFP 2 "comparison_operator" - [(match_operand:SF 0 "reg_or_0_operand" "fG") - (match_operand:SF 1 "reg_or_0_operand" "fG")]))] - "! TARGET_SOFT_FLOAT" - "fcmp,sgl,%Y2 %r0,%r1" - [(set_attr "length" "4") - (set_attr "type" "fpcc")]) - -(define_insn "" - [(set (reg:CCFP 0) - (match_operator:CCFP 2 "comparison_operator" - [(match_operand:DF 0 "reg_or_0_operand" "fG") - (match_operand:DF 1 "reg_or_0_operand" "fG")]))] - "! TARGET_SOFT_FLOAT" - "fcmp,dbl,%Y2 %r0,%r1" - [(set_attr "length" "4") - (set_attr "type" "fpcc")]) - -;; scc insns. - -(define_expand "seq" - [(set (match_operand:SI 0 "register_operand" "") - (eq:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - /* set up operands from compare. */ - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; - /* fall through and generate default code */ -}") - -(define_expand "sne" - [(set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "slt" - [(set (match_operand:SI 0 "register_operand" "") - (lt:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sgt" - [(set (match_operand:SI 0 "register_operand" "") - (gt:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sle" - [(set (match_operand:SI 0 "register_operand" "") - (le:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sge" - [(set (match_operand:SI 0 "register_operand" "") - (ge:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sltu" - [(set (match_operand:SI 0 "register_operand" "") - (ltu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sgtu" - [(set (match_operand:SI 0 "register_operand" "") - (gtu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sleu" - [(set (match_operand:SI 0 "register_operand" "") - (leu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sgeu" - [(set (match_operand:SI 0 "register_operand" "") - (geu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -;; Instruction canonicalization puts immediate operands second, which -;; is the reverse of what we want. - -(define_insn "scc" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 3 "comparison_operator" - [(match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "arith11_operand" "rI")]))] - "" - "com%I2clr,%B3 %2,%1,%0\;ldi 1,%0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -(define_insn "iorscc" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (match_operator:SI 3 "comparison_operator" - [(match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "arith11_operand" "rI")]) - (match_operator:SI 6 "comparison_operator" - [(match_operand:SI 4 "register_operand" "r") - (match_operand:SI 5 "arith11_operand" "rI")])))] - "" - "com%I2clr,%S3 %2,%1,0\;com%I5clr,%B6 %5,%4,%0\;ldi 1,%0" - [(set_attr "type" "binary") - (set_attr "length" "12")]) - -;; Combiner patterns for common operations performed with the output -;; from an scc insn (negscc and incscc). -(define_insn "negscc" - [(set (match_operand:SI 0 "register_operand" "=r") - (neg:SI (match_operator:SI 3 "comparison_operator" - [(match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "arith11_operand" "rI")])))] - "" - "com%I2clr,%B3 %2,%1,%0\;ldi -1,%0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -;; Patterns for adding/subtracting the result of a boolean expression from -;; a register. First we have special patterns that make use of the carry -;; bit, and output only two instructions. For the cases we can't in -;; general do in two instructions, the incscc pattern at the end outputs -;; two or three instructions. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (leu:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "arith11_operand" "rI")) - (match_operand:SI 1 "register_operand" "r")))] - "" - "sub%I3 %3,%2,0\;addc 0,%1,%0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -; This need only accept registers for op3, since canonicalization -; replaces geu with gtu when op3 is an integer. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (geu:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "register_operand" "r")) - (match_operand:SI 1 "register_operand" "r")))] - "" - "sub %2,%3,0\;addc 0,%1,%0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -; Match only integers for op3 here. This is used as canonical form of the -; geu pattern when op3 is an integer. Don't match registers since we can't -; make better code than the general incscc pattern. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (gtu:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "int11_operand" "I")) - (match_operand:SI 1 "register_operand" "r")))] - "" - "addi %k3,%2,0\;addc 0,%1,%0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -(define_insn "incscc" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (plus:SI (match_operator:SI 4 "comparison_operator" - [(match_operand:SI 2 "register_operand" "r,r") - (match_operand:SI 3 "arith11_operand" "rI,rI")]) - (match_operand:SI 1 "register_operand" "0,?r")))] - "" - "@ - com%I3clr,%B4 %3,%2,0\;addi 1,%0,%0 - com%I3clr,%B4 %3,%2,0\;addi,tr 1,%1,%0\;copy %1,%0" - [(set_attr "type" "binary,binary") - (set_attr "length" "8,12")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (match_operand:SI 1 "register_operand" "r") - (gtu:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "arith11_operand" "rI"))))] - "" - "sub%I3 %3,%2,0\;subb %1,0,%0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r") - (gtu:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "arith11_operand" "rI"))) - (match_operand:SI 4 "register_operand" "r")))] - "" - "sub%I3 %3,%2,0\;subb %1,%4,%0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -; This need only accept registers for op3, since canonicalization -; replaces ltu with leu when op3 is an integer. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (match_operand:SI 1 "register_operand" "r") - (ltu:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "register_operand" "r"))))] - "" - "sub %2,%3,0\;subb %1,0,%0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r") - (ltu:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "register_operand" "r"))) - (match_operand:SI 4 "register_operand" "r")))] - "" - "sub %2,%3,0\;subb %1,%4,%0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -; Match only integers for op3 here. This is used as canonical form of the -; ltu pattern when op3 is an integer. Don't match registers since we can't -; make better code than the general incscc pattern. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (match_operand:SI 1 "register_operand" "r") - (leu:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "int11_operand" "I"))))] - "" - "addi %k3,%2,0\;subb %1,0,%0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r") - (leu:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "int11_operand" "I"))) - (match_operand:SI 4 "register_operand" "r")))] - "" - "addi %k3,%2,0\;subb %1,%4,%0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -(define_insn "decscc" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (minus:SI (match_operand:SI 1 "register_operand" "0,?r") - (match_operator:SI 4 "comparison_operator" - [(match_operand:SI 2 "register_operand" "r,r") - (match_operand:SI 3 "arith11_operand" "rI,rI")])))] - "" - "@ - com%I3clr,%B4 %3,%2,0\;addi -1,%0,%0 - com%I3clr,%B4 %3,%2,0\;addi,tr -1,%1,%0\;copy %1,%0" - [(set_attr "type" "binary,binary") - (set_attr "length" "8,12")]) - -; Patterns for max and min. (There is no need for an earlyclobber in the -; last alternative since the middle alternative will match if op0 == op1.) - -(define_insn "sminsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (smin:SI (match_operand:SI 1 "register_operand" "%0,0,r") - (match_operand:SI 2 "arith11_operand" "r,I,M")))] - "" - "@ - comclr,> %2,%0,0\;copy %2,%0 - comiclr,> %2,%0,0\;ldi %2,%0 - comclr,> %1,%2,%0\;copy %1,%0" -[(set_attr "type" "multi,multi,multi") - (set_attr "length" "8,8,8")]) - -(define_insn "uminsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (umin:SI (match_operand:SI 1 "register_operand" "%0,0") - (match_operand:SI 2 "arith11_operand" "r,I")))] - "" - "@ - comclr,>> %2,%0,0\;copy %2,%0 - comiclr,>> %2,%0,0\;ldi %2,%0" -[(set_attr "type" "multi,multi") - (set_attr "length" "8,8")]) - -(define_insn "smaxsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (smax:SI (match_operand:SI 1 "register_operand" "%0,0,r") - (match_operand:SI 2 "arith11_operand" "r,I,M")))] - "" - "@ - comclr,< %2,%0,0\;copy %2,%0 - comiclr,< %2,%0,0\;ldi %2,%0 - comclr,< %1,%2,%0\;copy %1,%0" -[(set_attr "type" "multi,multi,multi") - (set_attr "length" "8,8,8")]) - -(define_insn "umaxsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (umax:SI (match_operand:SI 1 "register_operand" "%0,0") - (match_operand:SI 2 "arith11_operand" "r,I")))] - "" - "@ - comclr,<< %2,%0,0\;copy %2,%0 - comiclr,<< %2,%0,0\;ldi %2,%0" -[(set_attr "type" "multi,multi") - (set_attr "length" "8,8")]) - -(define_insn "abssi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (abs:SI (match_operand:SI 1 "register_operand" "r")))] - "" - "or,>= %%r0,%1,%0\;subi 0,%0,%0" - [(set_attr "type" "multi") - (set_attr "length" "8")]) - -;;; Experimental conditional move patterns - -(define_expand "movsicc" - [(set (match_operand:SI 0 "register_operand" "") - (if_then_else:SI - (match_operator 1 "comparison_operator" - [(match_dup 4) - (match_dup 5)]) - (match_operand:SI 2 "reg_or_cint_move_operand" "") - (match_operand:SI 3 "reg_or_cint_move_operand" "")))] - "" - " -{ - enum rtx_code code = GET_CODE (operands[1]); - - if (hppa_branch_type != CMP_SI) - FAIL; - - /* operands[1] is currently the result of compare_from_rtx. We want to - emit a compare of the original operands. */ - operands[1] = gen_rtx_fmt_ee (code, SImode, hppa_compare_op0, hppa_compare_op1); - operands[4] = hppa_compare_op0; - operands[5] = hppa_compare_op1; -}") - -; We need the first constraint alternative in order to avoid -; earlyclobbers on all other alternatives. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") - (if_then_else:SI - (match_operator 5 "comparison_operator" - [(match_operand:SI 3 "register_operand" "r,r,r,r,r") - (match_operand:SI 4 "arith11_operand" "rI,rI,rI,rI,rI")]) - (match_operand:SI 1 "reg_or_cint_move_operand" "0,r,J,N,K") - (const_int 0)))] - "" - "@ - com%I4clr,%S5 %4,%3,0\;ldi 0,%0 - com%I4clr,%B5 %4,%3,%0\;copy %1,%0 - com%I4clr,%B5 %4,%3,%0\;ldi %1,%0 - com%I4clr,%B5 %4,%3,%0\;ldil L'%1,%0 - com%I4clr,%B5 %4,%3,%0\;zdepi %Z1,%0" - [(set_attr "type" "multi,multi,multi,multi,nullshift") - (set_attr "length" "8,8,8,8,8")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r") - (if_then_else:SI - (match_operator 5 "comparison_operator" - [(match_operand:SI 3 "register_operand" "r,r,r,r,r,r,r,r") - (match_operand:SI 4 "arith11_operand" "rI,rI,rI,rI,rI,rI,rI,rI")]) - (match_operand:SI 1 "reg_or_cint_move_operand" "0,0,0,0,r,J,N,K") - (match_operand:SI 2 "reg_or_cint_move_operand" "r,J,N,K,0,0,0,0")))] - "" - "@ - com%I4clr,%S5 %4,%3,0\;copy %2,%0 - com%I4clr,%S5 %4,%3,0\;ldi %2,%0 - com%I4clr,%S5 %4,%3,0\;ldil L'%2,%0 - com%I4clr,%S5 %4,%3,0\;zdepi %Z2,%0 - com%I4clr,%B5 %4,%3,0\;copy %1,%0 - com%I4clr,%B5 %4,%3,0\;ldi %1,%0 - com%I4clr,%B5 %4,%3,0\;ldil L'%1,%0 - com%I4clr,%B5 %4,%3,0\;zdepi %Z1,%0" - [(set_attr "type" "multi,multi,multi,nullshift,multi,multi,multi,nullshift") - (set_attr "length" "8,8,8,8,8,8,8,8")]) - -;; Conditional Branches - -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (EQ, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - /* set up operands from compare. */ - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; - /* fall through and generate default code */ -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (NE, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (GT, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (LT, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (GE, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (le (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (LE, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -;; Match the branch patterns. - - -;; Note a long backward conditional branch with an annulled delay slot -;; has a length of 12. -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 3 "comparison_operator" - [(match_operand:SI 1 "reg_or_0_operand" "rM") - (match_operand:SI 2 "arith5_operand" "rL")]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -{ - return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn), - get_attr_length (insn), 0, insn); -}" -[(set_attr "type" "cbranch") - (set (attr "length") - (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) - (const_int 262100)) - (const_int 8) - (eq (symbol_ref "flag_pic") (const_int 0)) - (const_int 20)] - (const_int 28)))]) - -;; Match the negated branch. - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 3 "comparison_operator" - [(match_operand:SI 1 "reg_or_0_operand" "rM") - (match_operand:SI 2 "arith5_operand" "rL")]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -{ - return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn), - get_attr_length (insn), 1, insn); -}" -[(set_attr "type" "cbranch") - (set (attr "length") - (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) - (const_int 262100)) - (const_int 8) - (eq (symbol_ref "flag_pic") (const_int 0)) - (const_int 20)] - (const_int 28)))]) - -;; Branch on Bit patterns. -(define_insn "" - [(set (pc) - (if_then_else - (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "uint5_operand" "")) - (const_int 0)) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "* -{ - return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), - get_attr_length (insn), 0, insn, 0); -}" -[(set_attr "type" "cbranch") - (set (attr "length") - (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)))]) - -(define_insn "" - [(set (pc) - (if_then_else - (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "uint5_operand" "")) - (const_int 0)) - (pc) - (label_ref (match_operand 2 "" ""))))] - "" - "* -{ - return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), - get_attr_length (insn), 1, insn, 0); -}" -[(set_attr "type" "cbranch") - (set (attr "length") - (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)))]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "uint5_operand" "")) - (const_int 0)) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "* -{ - return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), - get_attr_length (insn), 0, insn, 1); -}" -[(set_attr "type" "cbranch") - (set (attr "length") - (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)))]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "uint5_operand" "")) - (const_int 0)) - (pc) - (label_ref (match_operand 2 "" ""))))] - "" - "* -{ - return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), - get_attr_length (insn), 1, insn, 1); -}" -[(set_attr "type" "cbranch") - (set (attr "length") - (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)))]) - -;; Branch on Variable Bit patterns. -(define_insn "" - [(set (pc) - (if_then_else - (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "register_operand" "q")) - (const_int 0)) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "* -{ - return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn), - get_attr_length (insn), 0, insn, 0); -}" -[(set_attr "type" "cbranch") - (set (attr "length") - (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)))]) - -(define_insn "" - [(set (pc) - (if_then_else - (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "register_operand" "q")) - (const_int 0)) - (pc) - (label_ref (match_operand 2 "" ""))))] - "" - "* -{ - return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn), - get_attr_length (insn), 1, insn, 0); -}" -[(set_attr "type" "cbranch") - (set (attr "length") - (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)))]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "register_operand" "q")) - (const_int 0)) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "* -{ - return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn), - get_attr_length (insn), 0, insn, 1); -}" -[(set_attr "type" "cbranch") - (set (attr "length") - (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)))]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "register_operand" "q")) - (const_int 0)) - (pc) - (label_ref (match_operand 2 "" ""))))] - "" - "* -{ - return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn), - get_attr_length (insn), 1, insn, 1); -}" -[(set_attr "type" "cbranch") - (set (attr "length") - (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)))]) - -;; Floating point branches -(define_insn "" - [(set (pc) (if_then_else (ne (reg:CCFP 0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "! TARGET_SOFT_FLOAT" - "* -{ - if (INSN_ANNULLED_BRANCH_P (insn)) - return \"ftest\;bl,n %0,0\"; - else - return \"ftest\;bl%* %0,0\"; -}" - [(set_attr "type" "fbranch") - (set_attr "length" "8")]) - -(define_insn "" - [(set (pc) (if_then_else (ne (reg:CCFP 0) (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "! TARGET_SOFT_FLOAT" - "* -{ - if (INSN_ANNULLED_BRANCH_P (insn)) - return \"ftest\;add,tr 0,0,0\;bl,n %0,0\"; - else - return \"ftest\;add,tr 0,0,0\;bl%* %0,0\"; -}" - [(set_attr "type" "fbranch") - (set_attr "length" "12")]) - -;; Move instructions - -(define_expand "movsi" - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, SImode, 0)) - DONE; -}") - -;; Reloading an SImode or DImode value requires a scratch register if -;; going in to or out of float point registers. - -(define_expand "reload_insi" - [(set (match_operand:SI 0 "register_operand" "=Z") - (match_operand:SI 1 "non_hard_reg_operand" "")) - (clobber (match_operand:SI 2 "register_operand" "=&r"))] - "" - " -{ - if (emit_move_sequence (operands, SImode, operands[2])) - DONE; - - /* We don't want the clobber emitted, so handle this ourselves. */ - emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); - DONE; -}") - -(define_expand "reload_outsi" - [(set (match_operand:SI 0 "non_hard_reg_operand" "") - (match_operand:SI 1 "register_operand" "Z")) - (clobber (match_operand:SI 2 "register_operand" "=&r"))] - "" - " -{ - if (emit_move_sequence (operands, SImode, operands[2])) - DONE; - - /* We don't want the clobber emitted, so handle this ourselves. */ - emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); - DONE; -}") - -;;; pic symbol references - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "symbolic_operand" ""))))] - "flag_pic && operands[1] == pic_offset_table_rtx" - "ldw T'%2(%1),%0" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" - "=r,r,r,r,r,Q,*q,!f,f,*TR") - (match_operand:SI 1 "move_operand" - "r,J,N,K,RQ,rM,rM,!fM,*RT,f"))] - "(register_operand (operands[0], SImode) - || reg_or_0_operand (operands[1], SImode)) - && ! TARGET_SOFT_FLOAT" - "@ - copy %1,%0 - ldi %1,%0 - ldil L'%1,%0 - zdepi %Z1,%0 - ldw%M1 %1,%0 - stw%M0 %r1,%0 - mtsar %r1 - fcpy,sgl %r1,%0 - fldw%F1 %1,%0 - fstw%F0 %1,%0" - [(set_attr "type" "move,move,move,shift,load,store,move,fpalu,fpload,fpstore") - (set_attr "pa_combine_type" "addmove") - (set_attr "length" "4,4,4,4,4,4,4,4,4,4")]) - -(define_insn "" - [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" - "=r,r,r,r,r,Q,*q") - (match_operand:SI 1 "move_operand" - "r,J,N,K,RQ,rM,rM"))] - "(register_operand (operands[0], SImode) - || reg_or_0_operand (operands[1], SImode)) - && TARGET_SOFT_FLOAT" - "@ - copy %1,%0 - ldi %1,%0 - ldil L'%1,%0 - zdepi %Z1,%0 - ldw%M1 %1,%0 - stw%M0 %r1,%0 - mtsar %r1" - [(set_attr "type" "move,move,move,move,load,store,move") - (set_attr "pa_combine_type" "addmove") - (set_attr "length" "4,4,4,4,4,4,4")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (mem:SI (plus:SI (match_operand:SI 1 "basereg_operand" "r") - (match_operand:SI 2 "register_operand" "r"))))] - "! TARGET_DISABLE_INDEXING" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[2] == hard_frame_pointer_rtx - || operands[2] == stack_pointer_rtx) - return \"ldwx %1(0,%2),%0\"; - else - return \"ldwx %2(0,%1),%0\"; -}" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "basereg_operand" "r"))))] - "! TARGET_DISABLE_INDEXING" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[1] == hard_frame_pointer_rtx - || operands[1] == stack_pointer_rtx) - return \"ldwx %2(0,%1),%0\"; - else - return \"ldwx %1(0,%2),%0\"; -}" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -;; Load or store with base-register modification. - -(define_insn "pre_ldwm" - [(set (match_operand:SI 0 "register_operand" "=r") - (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "+r") - (match_operand:SI 2 "pre_cint_operand" "")))) - (set (match_dup 1) - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "* -{ - if (INTVAL (operands[2]) < 0) - return \"ldwm %2(0,%1),%0\"; - return \"ldws,mb %2(0,%1),%0\"; -}" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "pre_stwm" - [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "+r") - (match_operand:SI 1 "pre_cint_operand" ""))) - (match_operand:SI 2 "reg_or_0_operand" "rM")) - (set (match_dup 0) - (plus:SI (match_dup 0) (match_dup 1)))] - "" - "* -{ - if (INTVAL (operands[1]) < 0) - return \"stwm %r2,%1(0,%0)\"; - return \"stws,mb %r2,%1(0,%0)\"; -}" - [(set_attr "type" "store") - (set_attr "length" "4")]) - -(define_insn "post_ldwm" - [(set (match_operand:SI 0 "register_operand" "=r") - (mem:SI (match_operand:SI 1 "register_operand" "+r"))) - (set (match_dup 1) - (plus:SI (match_dup 1) - (match_operand:SI 2 "post_cint_operand" "")))] - "" - "* -{ - if (INTVAL (operands[2]) > 0) - return \"ldwm %2(0,%1),%0\"; - return \"ldws,ma %2(0,%1),%0\"; -}" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "post_stwm" - [(set (mem:SI (match_operand:SI 0 "register_operand" "+r")) - (match_operand:SI 1 "reg_or_0_operand" "rM")) - (set (match_dup 0) - (plus:SI (match_dup 0) - (match_operand:SI 2 "post_cint_operand" "")))] - "" - "* -{ - if (INTVAL (operands[2]) > 0) - return \"stwm %r1,%2(0,%0)\"; - return \"stws,ma %r1,%2(0,%0)\"; -}" - [(set_attr "type" "store") - (set_attr "length" "4")]) - -;; For pic -;; Note since this pattern can be created at reload time (via movsi), all -;; the same rules for movsi apply here. (no new pseudos, no temporaries). -(define_insn "pic_load_label" - [(set (match_operand:SI 0 "register_operand" "=a") - (match_operand:SI 1 "pic_label_operand" ""))] - "" - "* -{ - rtx label_rtx = gen_label_rtx (); - rtx xoperands[3]; - extern FILE *asm_out_file; - - xoperands[0] = operands[0]; - xoperands[1] = operands[1]; - xoperands[2] = label_rtx; - output_asm_insn (\"bl .+8,%0\", xoperands); - output_asm_insn (\"depi 0,31,2,%0\", xoperands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", - CODE_LABEL_NUMBER (label_rtx)); - - /* If we're trying to load the address of a label that happens to be - close, then we can use a shorter sequence. */ - if (GET_CODE (operands[1]) == LABEL_REF - && insn_addresses - && abs (insn_addresses[INSN_UID (XEXP (operands[1], 0))] - - insn_addresses[INSN_UID (insn)]) < 8100) - { - /* Prefixing with R% here is wrong, it extracts just 11 bits and is - always non-negative. */ - output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands); - } - else - { - output_asm_insn (\"addil L%%%1-%2,%0\", xoperands); - output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands); - } - return \"\"; -}" - [(set_attr "type" "multi") - (set_attr "length" "16")]) ; 12 or 16 - -(define_insn "pic2_highpart" - [(set (match_operand:SI 0 "register_operand" "=a") - (plus:SI (match_operand:SI 1 "register_operand" "r") - (high:SI (match_operand 2 "" ""))))] - "symbolic_operand (operands[2], Pmode) - && ! function_label_operand (operands[2]) - && flag_pic == 2" - "addil LT'%G2,%1" - [(set_attr "type" "binary") - (set_attr "length" "4")]) - -; We need this to make sure CSE doesn't simplify a memory load with a -; symbolic address, whose content it think it knows. For PIC, what CSE -; think is the real value will be the address of that value. -(define_insn "pic2_lo_sum" - [(set (match_operand:SI 0 "register_operand" "=r") - (mem:SI (lo_sum:SI (match_operand:SI 1 "register_operand" "r") - (unspec:SI [(match_operand:SI 2 "symbolic_operand" "")] 0))))] - "" - "* -{ - if (flag_pic != 2) - abort (); - return \"ldw RT'%G2(%1),%0\"; -}" - [(set_attr "type" "load") - (set_attr "length" "4")]) - - -;; Always use addil rather than ldil;add sequences. This allows the -;; HP linker to eliminate the dp relocation if the symbolic operand -;; lives in the TEXT space. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=a") - (high:SI (match_operand 1 "" "")))] - "symbolic_operand (operands[1], Pmode) - && ! function_label_operand (operands[1]) - && ! read_only_operand (operands[1]) - && ! flag_pic" - "* -{ - if (TARGET_LONG_LOAD_STORE) - return \"addil NLR'%H1,%%r27\;ldo N'%H1(%%r1),%%r1\"; - else - return \"addil LR'%H1,%%r27\"; -}" - [(set_attr "type" "binary") - (set (attr "length") - (if_then_else (eq (symbol_ref "TARGET_LONG_LOAD_STORE") (const_int 0)) - (const_int 4) - (const_int 8)))]) - - -;; This is for use in the prologue/epilogue code. We need it -;; to add large constants to a stack pointer or frame pointer. -;; Because of the additional %r1 pressure, we probably do not -;; want to use this in general code, so make it available -;; only after reload. -(define_insn "add_high_const" - [(set (match_operand:SI 0 "register_operand" "=!a,*r") - (plus:SI (match_operand:SI 1 "register_operand" "r,r") - (high:SI (match_operand 2 "const_int_operand" ""))))] - "reload_completed" - "@ - addil L'%G2,%1 - ldil L'%G2,%0\;addl %0,%1,%0" - [(set_attr "type" "binary,binary") - (set_attr "length" "4,8")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (high:SI (match_operand 1 "" "")))] - "(!flag_pic || !symbolic_operand (operands[1]), Pmode) - && !is_function_label_plus_const (operands[1])" - "* -{ - if (symbolic_operand (operands[1], Pmode)) - return \"ldil LR'%H1,%0\"; - else - return \"ldil L'%G1,%0\"; -}" - [(set_attr "type" "move") - (set_attr "length" "4")]) - -(define_insn "" - [(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")))] - "!is_function_label_plus_const (operands[2])" - "* -{ - if (flag_pic && symbolic_operand (operands[2], Pmode)) - abort (); - else if (symbolic_operand (operands[2], Pmode)) - return \"ldo RR'%G2(%1),%0\"; - else - return \"ldo R'%G2(%1),%0\"; -}" - [(set_attr "type" "move") - (set_attr "length" "4")]) - -;; Now that a symbolic_address plus a constant is broken up early -;; in the compilation phase (for better CSE) we need a special -;; combiner pattern to load the symbolic address plus the constant -;; in only 2 instructions. (For cases where the symbolic address -;; was not a common subexpression.) -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "symbolic_operand" "")) - (clobber (match_operand:SI 2 "register_operand" ""))] - "! (flag_pic && pic_label_operand (operands[1], SImode))" - [(set (match_dup 2) (high:SI (match_dup 1))) - (set (match_dup 0) (lo_sum:SI (match_dup 2) (match_dup 1)))] - "") - -;; hppa_legitimize_address goes to a great deal of trouble to -;; create addresses which use indexing. In some cases, this -;; is a lose because there isn't any store instructions which -;; allow indexed addresses (with integer register source). -;; -;; These define_splits try to turn a 3 insn store into -;; a 2 insn store with some creative RTL rewriting. -(define_split - [(set (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "shadd_operand" "")) - (plus:SI (match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "const_int_operand" "")))) - (match_operand:SI 4 "register_operand" "")) - (clobber (match_operand:SI 5 "register_operand" ""))] - "" - [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1)) - (match_dup 2))) - (set (mem:SI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))] - "") - -(define_split - [(set (mem:HI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "shadd_operand" "")) - (plus:SI (match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "const_int_operand" "")))) - (match_operand:HI 4 "register_operand" "")) - (clobber (match_operand:SI 5 "register_operand" ""))] - "" - [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1)) - (match_dup 2))) - (set (mem:HI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))] - "") - -(define_split - [(set (mem:QI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "shadd_operand" "")) - (plus:SI (match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "const_int_operand" "")))) - (match_operand:QI 4 "register_operand" "")) - (clobber (match_operand:SI 5 "register_operand" ""))] - "" - [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1)) - (match_dup 2))) - (set (mem:QI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))] - "") - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, HImode, 0)) - DONE; -}") - -(define_insn "" - [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q,*q,!f") - (match_operand:HI 1 "move_operand" "r,J,N,K,RQ,rM,rM,!fM"))] - "register_operand (operands[0], HImode) - || reg_or_0_operand (operands[1], HImode)" - "@ - copy %1,%0 - ldi %1,%0 - ldil L'%1,%0 - zdepi %Z1,%0 - ldh%M1 %1,%0 - sth%M0 %r1,%0 - mtsar %r1 - fcpy,sgl %r1,%0" - [(set_attr "type" "move,move,move,shift,load,store,move,fpalu") - (set_attr "pa_combine_type" "addmove") - (set_attr "length" "4,4,4,4,4,4,4,4")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (mem:HI (plus:SI (match_operand:SI 1 "basereg_operand" "r") - (match_operand:SI 2 "register_operand" "r"))))] - "! TARGET_DISABLE_INDEXING" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[2] == hard_frame_pointer_rtx - || operands[2] == stack_pointer_rtx) - return \"ldhx %1(0,%2),%0\"; - else - return \"ldhx %2(0,%1),%0\"; -}" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "basereg_operand" "r"))))] - "! TARGET_DISABLE_INDEXING" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[1] == hard_frame_pointer_rtx - || operands[1] == stack_pointer_rtx) - return \"ldhx %2(0,%1),%0\"; - else - return \"ldhx %1(0,%2),%0\"; -}" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -; Now zero extended variants. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (mem:HI - (plus:SI - (match_operand:SI 1 "basereg_operand" "r") - (match_operand:SI 2 "register_operand" "r")))))] - "! TARGET_DISABLE_INDEXING" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[2] == hard_frame_pointer_rtx - || operands[2] == stack_pointer_rtx) - return \"ldhx %1(0,%2),%0\"; - else - return \"ldhx %2(0,%1),%0\"; -}" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (mem:HI - (plus:SI - (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "basereg_operand" "r")))))] - "! TARGET_DISABLE_INDEXING" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[1] == hard_frame_pointer_rtx - || operands[1] == stack_pointer_rtx) - return \"ldhx %2(0,%1),%0\"; - else - return \"ldhx %1(0,%2),%0\"; -}" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "+r") - (match_operand:SI 2 "int5_operand" "L")))) - (set (match_dup 1) - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "ldhs,mb %2(0,%1),%0" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -; And a zero extended variant. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (mem:HI - (plus:SI - (match_operand:SI 1 "register_operand" "+r") - (match_operand:SI 2 "int5_operand" "L"))))) - (set (match_dup 1) - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "ldhs,mb %2(0,%1),%0" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "" - [(set (mem:HI (plus:SI (match_operand:SI 0 "register_operand" "+r") - (match_operand:SI 1 "int5_operand" "L"))) - (match_operand:HI 2 "reg_or_0_operand" "rM")) - (set (match_dup 0) - (plus:SI (match_dup 0) (match_dup 1)))] - "" - "sths,mb %r2,%1(0,%0)" - [(set_attr "type" "store") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (high:HI (match_operand 1 "const_int_operand" "")))] - "" - "ldil L'%G1,%0" - [(set_attr "type" "move") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (lo_sum:HI (match_operand:HI 1 "register_operand" "r") - (match_operand 2 "const_int_operand" "")))] - "" - "ldo R'%G2(%1),%0" - [(set_attr "type" "move") - (set_attr "length" "4")]) - -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, QImode, 0)) - DONE; -}") - -(define_insn "" - [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q,*q,!f") - (match_operand:QI 1 "move_operand" "r,J,N,K,RQ,rM,rM,!fM"))] - "register_operand (operands[0], QImode) - || reg_or_0_operand (operands[1], QImode)" - "@ - copy %1,%0 - ldi %1,%0 - ldil L'%1,%0 - zdepi %Z1,%0 - ldb%M1 %1,%0 - stb%M0 %r1,%0 - mtsar %r1 - fcpy,sgl %r1,%0" - [(set_attr "type" "move,move,move,shift,load,store,move,fpalu") - (set_attr "pa_combine_type" "addmove") - (set_attr "length" "4,4,4,4,4,4,4,4")]) - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (mem:QI (plus:SI (match_operand:SI 1 "basereg_operand" "r") - (match_operand:SI 2 "register_operand" "r"))))] - "! TARGET_DISABLE_INDEXING" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[2] == hard_frame_pointer_rtx - || operands[2] == stack_pointer_rtx) - return \"ldbx %1(0,%2),%0\"; - else - return \"ldbx %2(0,%1),%0\"; -}" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "basereg_operand" "r"))))] - "! TARGET_DISABLE_INDEXING" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[1] == hard_frame_pointer_rtx - || operands[1] == stack_pointer_rtx) - return \"ldbx %2(0,%1),%0\"; - else - return \"ldbx %1(0,%2),%0\"; -}" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -; Indexed byte load with zero extension to SImode or HImode. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (mem:QI - (plus:SI - (match_operand:SI 1 "basereg_operand" "r") - (match_operand:SI 2 "register_operand" "r")))))] - "! TARGET_DISABLE_INDEXING" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[2] == hard_frame_pointer_rtx - || operands[2] == stack_pointer_rtx) - return \"ldbx %1(0,%2),%0\"; - else - return \"ldbx %2(0,%1),%0\"; -}" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (mem:QI - (plus:SI - (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "basereg_operand" "r")))))] - "! TARGET_DISABLE_INDEXING" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[1] == hard_frame_pointer_rtx - || operands[1] == stack_pointer_rtx) - return \"ldbx %2(0,%1),%0\"; - else - return \"ldbx %1(0,%2),%0\"; -}" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (zero_extend:HI (mem:QI - (plus:SI - (match_operand:SI 1 "basereg_operand" "r") - (match_operand:SI 2 "register_operand" "r")))))] - "! TARGET_DISABLE_INDEXING" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[2] == hard_frame_pointer_rtx - || operands[2] == stack_pointer_rtx) - return \"ldbx %1(0,%2),%0\"; - else - return \"ldbx %2(0,%1),%0\"; -}" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (zero_extend:HI (mem:QI - (plus:SI - (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "basereg_operand" "r")))))] - "! TARGET_DISABLE_INDEXING" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[1] == hard_frame_pointer_rtx - || operands[1] == stack_pointer_rtx) - return \"ldbx %2(0,%1),%0\"; - else - return \"ldbx %1(0,%2),%0\"; -}" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "+r") - (match_operand:SI 2 "int5_operand" "L")))) - (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))] - "" - "ldbs,mb %2(0,%1),%0" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -; Now the same thing with zero extensions. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (mem:QI (plus:SI - (match_operand:SI 1 "register_operand" "+r") - (match_operand:SI 2 "int5_operand" "L"))))) - (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))] - "" - "ldbs,mb %2(0,%1),%0" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (zero_extend:HI (mem:QI (plus:SI - (match_operand:SI 1 "register_operand" "+r") - (match_operand:SI 2 "int5_operand" "L"))))) - (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))] - "" - "ldbs,mb %2(0,%1),%0" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "" - [(set (mem:QI (plus:SI (match_operand:SI 0 "register_operand" "+r") - (match_operand:SI 1 "int5_operand" "L"))) - (match_operand:QI 2 "reg_or_0_operand" "rM")) - (set (match_dup 0) - (plus:SI (match_dup 0) (match_dup 1)))] - "" - "stbs,mb %r2,%1(0,%0)" - [(set_attr "type" "store") - (set_attr "length" "4")]) - -;; The definition of this insn does not really explain what it does, -;; but it should suffice -;; that anything generated as this insn will be recognized as one -;; and that it will not successfully combine with anything. -(define_expand "movstrsi" - [(parallel [(set (match_operand:BLK 0 "" "") - (match_operand:BLK 1 "" "")) - (clobber (match_dup 7)) - (clobber (match_dup 8)) - (clobber (match_dup 4)) - (clobber (match_dup 5)) - (clobber (match_dup 6)) - (use (match_operand:SI 2 "arith_operand" "")) - (use (match_operand:SI 3 "const_int_operand" ""))])] - "" - " -{ - int size, align; - - /* HP provides very fast block move library routine for the PA; - this routine includes: - - 4x4 byte at a time block moves, - 1x4 byte at a time with alignment checked at runtime with - attempts to align the source and destination as needed - 1x1 byte loop - - With that in mind, here's the heuristics to try and guess when - the inlined block move will be better than the library block - move: - - If the size isn't constant, then always use the library routines. - - If the size is large in respect to the known alignment, then use - the library routines. - - If the size is small in repsect to the known alignment, then open - code the copy (since that will lead to better scheduling). - - Else use the block move pattern. */ - - /* Undetermined size, use the library routine. */ - if (GET_CODE (operands[2]) != CONST_INT) - FAIL; - - size = INTVAL (operands[2]); - align = INTVAL (operands[3]); - align = align > 4 ? 4 : align; - - /* If size/alignment > 8 (eg size is large in respect to alignment), - then use the library routines. */ - if (size / align > 16) - FAIL; - - /* This does happen, but not often enough to worry much about. */ - if (size / align < MOVE_RATIO) - FAIL; - - /* Fall through means we're going to use our block move pattern. */ - operands[0] - = change_address (operands[0], VOIDmode, - copy_to_mode_reg (SImode, XEXP (operands[0], 0))); - operands[1] - = change_address (operands[1], VOIDmode, - copy_to_mode_reg (SImode, XEXP (operands[1], 0))); - operands[4] = gen_reg_rtx (SImode); - operands[5] = gen_reg_rtx (SImode); - operands[6] = gen_reg_rtx (SImode); - operands[7] = XEXP (operands[0], 0); - operands[8] = XEXP (operands[1], 0); -}") - -;; The operand constraints are written like this to support both compile-time -;; and run-time determined byte count. If the count is run-time determined, -;; the register with the byte count is clobbered by the copying code, and -;; therefore it is forced to operand 2. If the count is compile-time -;; determined, we need two scratch registers for the unrolled code. -(define_insn "movstrsi_internal" - [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r,r")) - (mem:BLK (match_operand:SI 1 "register_operand" "+r,r"))) - (clobber (match_dup 0)) - (clobber (match_dup 1)) - (clobber (match_operand:SI 2 "register_operand" "=r,r")) ;loop cnt/tmp - (clobber (match_operand:SI 3 "register_operand" "=&r,&r")) ;item tmp - (clobber (match_operand:SI 6 "register_operand" "=&r,&r")) ;item tmp2 - (use (match_operand:SI 4 "arith_operand" "J,2")) ;byte count - (use (match_operand:SI 5 "const_int_operand" "n,n"))] ;alignment - "" - "* return output_block_move (operands, !which_alternative);" - [(set_attr "type" "multi,multi")]) - -;; Floating point move insns - -;; This pattern forces (set (reg:DF ...) (const_double ...)) -;; to be reloaded by putting the constant into memory when -;; reg is a floating point register. -;; -;; For integer registers we use ldil;ldo to set the appropriate -;; value. -;; -;; This must come before the movdf pattern, and it must be present -;; to handle obscure reloading cases. -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=?r,f") - (match_operand:DF 1 "" "?F,m"))] - "GET_CODE (operands[1]) == CONST_DOUBLE - && operands[1] != CONST0_RTX (DFmode) - && ! TARGET_SOFT_FLOAT" - "* return (which_alternative == 0 ? output_move_double (operands) - : \"fldd%F1 %1,%0\");" - [(set_attr "type" "move,fpload") - (set_attr "length" "16,4")]) - -(define_expand "movdf" - [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, DFmode, 0)) - DONE; -}") - -;; Reloading an SImode or DImode value requires a scratch register if -;; going in to or out of float point registers. - -(define_expand "reload_indf" - [(set (match_operand:DF 0 "register_operand" "=Z") - (match_operand:DF 1 "non_hard_reg_operand" "")) - (clobber (match_operand:DF 2 "register_operand" "=&r"))] - "" - " -{ - if (emit_move_sequence (operands, DFmode, operands[2])) - DONE; - - /* We don't want the clobber emitted, so handle this ourselves. */ - emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); - DONE; -}") - -(define_expand "reload_outdf" - [(set (match_operand:DF 0 "non_hard_reg_operand" "") - (match_operand:DF 1 "register_operand" "Z")) - (clobber (match_operand:DF 2 "register_operand" "=&r"))] - "" - " -{ - if (emit_move_sequence (operands, DFmode, operands[2])) - DONE; - - /* We don't want the clobber emitted, so handle this ourselves. */ - emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); - DONE; -}") - -(define_insn "" - [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" - "=f,*r,RQ,?o,?Q,f,*r,*r") - (match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand" - "fG,*rG,f,*r,*r,RQ,o,RQ"))] - "(register_operand (operands[0], DFmode) - || reg_or_0_operand (operands[1], DFmode)) - && ! (GET_CODE (operands[1]) == CONST_DOUBLE - && GET_CODE (operands[0]) == MEM) - && ! TARGET_SOFT_FLOAT" - "* -{ - if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]) - || operands[1] == CONST0_RTX (DFmode)) - return output_fp_move_double (operands); - return output_move_double (operands); -}" - [(set_attr "type" "fpalu,move,fpstore,store,store,fpload,load,load") - (set_attr "length" "4,8,4,8,16,4,8,16")]) - -(define_insn "" - [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" - "=r,?o,?Q,r,r") - (match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand" - "rG,r,r,o,Q"))] - "(register_operand (operands[0], DFmode) - || reg_or_0_operand (operands[1], DFmode)) - && TARGET_SOFT_FLOAT" - "* -{ - return output_move_double (operands); -}" - [(set_attr "type" "move,store,store,load,load") - (set_attr "length" "8,8,16,8,16")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=fx") - (mem:DF (plus:SI (match_operand:SI 1 "basereg_operand" "r") - (match_operand:SI 2 "register_operand" "r"))))] - "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[2] == hard_frame_pointer_rtx - || operands[2] == stack_pointer_rtx) - return \"flddx %1(0,%2),%0\"; - else - return \"flddx %2(0,%1),%0\"; -}" - [(set_attr "type" "fpload") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=fx") - (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "basereg_operand" "r"))))] - "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[1] == hard_frame_pointer_rtx - || operands[1] == stack_pointer_rtx) - return \"flddx %2(0,%1),%0\"; - else - return \"flddx %1(0,%2),%0\"; -}" - [(set_attr "type" "fpload") - (set_attr "length" "4")]) - -(define_insn "" - [(set (mem:DF (plus:SI (match_operand:SI 1 "basereg_operand" "r") - (match_operand:SI 2 "register_operand" "r"))) - (match_operand:DF 0 "register_operand" "fx"))] - "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[2] == hard_frame_pointer_rtx - || operands[2] == stack_pointer_rtx) - return \"fstdx %0,%1(0,%2)\"; - else - return \"fstdx %0,%2(0,%1)\"; -}" - [(set_attr "type" "fpstore") - (set_attr "length" "4")]) - -(define_insn "" - [(set (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "basereg_operand" "r"))) - (match_operand:DF 0 "register_operand" "fx"))] - "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[1] == hard_frame_pointer_rtx - || operands[1] == stack_pointer_rtx) - return \"fstdx %0,%2(0,%1)\"; - else - return \"fstdx %0,%1(0,%2)\"; -}" - [(set_attr "type" "fpstore") - (set_attr "length" "4")]) - -(define_expand "movdi" - [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, DImode, 0)) - DONE; -}") - -(define_expand "reload_indi" - [(set (match_operand:DI 0 "register_operand" "=f") - (match_operand:DI 1 "non_hard_reg_operand" "")) - (clobber (match_operand:SI 2 "register_operand" "=&r"))] - "" - " -{ - if (emit_move_sequence (operands, DImode, operands[2])) - DONE; - - /* We don't want the clobber emitted, so handle this ourselves. */ - emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); - DONE; -}") - -(define_expand "reload_outdi" - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "register_operand" "f")) - (clobber (match_operand:SI 2 "register_operand" "=&r"))] - "" - " -{ - if (emit_move_sequence (operands, DImode, operands[2])) - DONE; - - /* We don't want the clobber emitted, so handle this ourselves. */ - emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); - DONE; -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (high:DI (match_operand 1 "" "")))] - "" - "* -{ - rtx op0 = operands[0]; - rtx op1 = operands[1]; - - if (GET_CODE (op1) == CONST_INT) - { - operands[0] = operand_subword (op0, 1, 0, DImode); - output_asm_insn (\"ldil L'%1,%0\", operands); - - operands[0] = operand_subword (op0, 0, 0, DImode); - if (INTVAL (op1) < 0) - output_asm_insn (\"ldi -1,%0\", operands); - else - output_asm_insn (\"ldi 0,%0\", operands); - return \"\"; - } - else if (GET_CODE (op1) == CONST_DOUBLE) - { - operands[0] = operand_subword (op0, 1, 0, DImode); - operands[1] = GEN_INT (CONST_DOUBLE_LOW (op1)); - output_asm_insn (\"ldil L'%1,%0\", operands); - - operands[0] = operand_subword (op0, 0, 0, DImode); - operands[1] = GEN_INT (CONST_DOUBLE_HIGH (op1)); - output_asm_insn (singlemove_string (operands), operands); - return \"\"; - } - else - abort (); -}" - [(set_attr "type" "move") - (set_attr "length" "8")]) - -;;; Experimental - -(define_insn "" - [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" - "=r,o,Q,r,r,r,f,f,*TR") - (match_operand:DI 1 "general_operand" - "rM,r,r,o*R,Q,i,fM,*TR,f"))] - "(register_operand (operands[0], DImode) - || reg_or_0_operand (operands[1], DImode)) - && ! TARGET_SOFT_FLOAT" - "* -{ - if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]) - || (operands[1] == CONST0_RTX (DImode))) - return output_fp_move_double (operands); - return output_move_double (operands); -}" - [(set_attr "type" "move,store,store,load,load,multi,fpalu,fpload,fpstore") - (set_attr "length" "8,8,16,8,16,16,4,4,4")]) - -(define_insn "" - [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" - "=r,o,Q,r,r,r") - (match_operand:DI 1 "general_operand" - "rM,r,r,o,Q,i"))] - "(register_operand (operands[0], DImode) - || reg_or_0_operand (operands[1], DImode)) - && TARGET_SOFT_FLOAT" - "* -{ - return output_move_double (operands); -}" - [(set_attr "type" "move,store,store,load,load,multi") - (set_attr "length" "8,8,16,8,16,16")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r,&r") - (lo_sum:DI (match_operand:DI 1 "register_operand" "0,r") - (match_operand:DI 2 "immediate_operand" "i,i")))] - "" - "* -{ - /* Don't output a 64 bit constant, since we can't trust the assembler to - handle it correctly. */ - if (GET_CODE (operands[2]) == CONST_DOUBLE) - operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2])); - if (which_alternative == 1) - output_asm_insn (\"copy %1,%0\", operands); - return \"ldo R'%G2(%R1),%R0\"; -}" - [(set_attr "type" "move,move") - (set_attr "length" "4,8")]) - -;; This pattern forces (set (reg:SF ...) (const_double ...)) -;; to be reloaded by putting the constant into memory when -;; reg is a floating point register. -;; -;; For integer registers we use ldil;ldo to set the appropriate -;; value. -;; -;; This must come before the movsf pattern, and it must be present -;; to handle obscure reloading cases. -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=?r,f") - (match_operand:SF 1 "" "?F,m"))] - "GET_CODE (operands[1]) == CONST_DOUBLE - && operands[1] != CONST0_RTX (SFmode) - && ! TARGET_SOFT_FLOAT" - "* return (which_alternative == 0 ? singlemove_string (operands) - : \" fldw%F1 %1,%0\");" - [(set_attr "type" "move,fpload") - (set_attr "length" "8,4")]) - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, SFmode, 0)) - DONE; -}") - -;; Reloading an SImode or DImode value requires a scratch register if -;; going in to or out of float point registers. - -(define_expand "reload_insf" - [(set (match_operand:SF 0 "register_operand" "=Z") - (match_operand:SF 1 "non_hard_reg_operand" "")) - (clobber (match_operand:SF 2 "register_operand" "=&r"))] - "" - " -{ - if (emit_move_sequence (operands, SFmode, operands[2])) - DONE; - - /* We don't want the clobber emitted, so handle this ourselves. */ - emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); - DONE; -}") - -(define_expand "reload_outsf" - [(set (match_operand:SF 0 "non_hard_reg_operand" "") - (match_operand:SF 1 "register_operand" "Z")) - (clobber (match_operand:SF 2 "register_operand" "=&r"))] - "" - " -{ - if (emit_move_sequence (operands, SFmode, operands[2])) - DONE; - - /* We don't want the clobber emitted, so handle this ourselves. */ - emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); - DONE; -}") - -(define_insn "" - [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" - "=f,r,f,r,RQ,Q") - (match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand" - "fG,rG,RQ,RQ,f,rG"))] - "(register_operand (operands[0], SFmode) - || reg_or_0_operand (operands[1], SFmode)) - && ! TARGET_SOFT_FLOAT" - "@ - fcpy,sgl %r1,%0 - copy %r1,%0 - fldw%F1 %1,%0 - ldw%M1 %1,%0 - fstw%F0 %r1,%0 - stw%M0 %r1,%0" - [(set_attr "type" "fpalu,move,fpload,load,fpstore,store") - (set_attr "pa_combine_type" "addmove") - (set_attr "length" "4,4,4,4,4,4")]) - -(define_insn "" - [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" - "=r,r,Q") - (match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand" - "rG,RQ,rG"))] - "(register_operand (operands[0], SFmode) - || reg_or_0_operand (operands[1], SFmode)) - && TARGET_SOFT_FLOAT" - "@ - copy %r1,%0 - ldw%M1 %1,%0 - stw%M0 %r1,%0" - [(set_attr "type" "move,load,store") - (set_attr "pa_combine_type" "addmove") - (set_attr "length" "4,4,4")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=fx") - (mem:SF (plus:SI (match_operand:SI 1 "basereg_operand" "r") - (match_operand:SI 2 "register_operand" "r"))))] - "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[2] == hard_frame_pointer_rtx - || operands[2] == stack_pointer_rtx) - return \"fldwx %1(0,%2),%0\"; - else - return \"fldwx %2(0,%1),%0\"; -}" - [(set_attr "type" "fpload") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=fx") - (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "basereg_operand" "r"))))] - "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[1] == hard_frame_pointer_rtx - || operands[1] == stack_pointer_rtx) - return \"fldwx %2(0,%1),%0\"; - else - return \"fldwx %1(0,%2),%0\"; -}" - [(set_attr "type" "fpload") - (set_attr "length" "4")]) - -(define_insn "" - [(set (mem:SF (plus:SI (match_operand:SI 1 "basereg_operand" "r") - (match_operand:SI 2 "register_operand" "r"))) - (match_operand:SF 0 "register_operand" "fx"))] - "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[2] == hard_frame_pointer_rtx - || operands[2] == stack_pointer_rtx) - return \"fstwx %0,%1(0,%2)\"; - else - return \"fstwx %0,%2(0,%1)\"; -}" - [(set_attr "type" "fpstore") - (set_attr "length" "4")]) - -(define_insn "" - [(set (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "basereg_operand" "r"))) - (match_operand:SF 0 "register_operand" "fx"))] - "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" - "* -{ - /* Reload can create backwards (relative to cse) unscaled index - address modes when eliminating registers and possibly for - pseudos that don't get hard registers. Deal with it. */ - if (operands[1] == hard_frame_pointer_rtx - || operands[1] == stack_pointer_rtx) - return \"fstwx %0,%2(0,%1)\"; - else - return \"fstwx %0,%1(0,%2)\"; -}" - [(set_attr "type" "fpstore") - (set_attr "length" "4")]) - - -;;- zero extension instructions -;; We have define_expand for zero extension patterns to make sure the -;; operands get loaded into registers. The define_insns accept -;; memory operands. This gives us better overall code than just -;; having a pattern that does or does not accept memory operands. - -(define_expand "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI - (match_operand:HI 1 "register_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (zero_extend:SI - (match_operand:HI 1 "move_operand" "r,RQ")))] - "GET_CODE (operands[1]) != CONST_INT" - "@ - extru %1,31,16,%0 - ldh%M1 %1,%0" - [(set_attr "type" "shift,load") - (set_attr "length" "4,4")]) - -(define_expand "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI - (match_operand:QI 1 "register_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (zero_extend:HI - (match_operand:QI 1 "move_operand" "r,RQ")))] - "GET_CODE (operands[1]) != CONST_INT" - "@ - extru %1,31,8,%0 - ldb%M1 %1,%0" - [(set_attr "type" "shift,load") - (set_attr "length" "4,4")]) - -(define_expand "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI - (match_operand:QI 1 "register_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (zero_extend:SI - (match_operand:QI 1 "move_operand" "r,RQ")))] - "GET_CODE (operands[1]) != CONST_INT" - "@ - extru %1,31,8,%0 - ldb%M1 %1,%0" - [(set_attr "type" "shift,load") - (set_attr "length" "4,4")]) - -;;- sign extension instructions - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))] - "" - "extrs %1,31,16,%0" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=r") - (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))] - "" - "extrs %1,31,8,%0" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))] - "" - "extrs %1,31,8,%0" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -;; Conversions between float and double. - -(define_insn "extendsfdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (float_extend:DF - (match_operand:SF 1 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fcnvff,sgl,dbl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "truncdfsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (float_truncate:SF - (match_operand:DF 1 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fcnvff,dbl,sgl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -;; Conversion between fixed point and floating point. -;; Note that among the fix-to-float insns -;; the ones that start with SImode come first. -;; That is so that an operand that is a CONST_INT -;; (and therefore lacks a specific machine mode). -;; will be recognized as SImode (which is always valid) -;; rather than as QImode or HImode. - -;; This pattern forces (set (reg:SF ...) (float:SF (const_int ...))) -;; to be reloaded by putting the constant into memory. -;; It must come before the more general floatsisf2 pattern. -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (float:SF (match_operand:SI 1 "const_int_operand" "m")))] - "! TARGET_SOFT_FLOAT" - "fldw%F1 %1,%0\;fcnvxf,sgl,sgl %0,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "8")]) - -(define_insn "floatsisf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (float:SF (match_operand:SI 1 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fcnvxf,sgl,sgl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - - -;; This pattern forces (set (reg:DF ...) (float:DF (const_int ...))) -;; to be reloaded by putting the constant into memory. -;; It must come before the more general floatsidf2 pattern. -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (float:DF (match_operand:SI 1 "const_int_operand" "m")))] - "! TARGET_SOFT_FLOAT" - "fldw%F1 %1,%0\;fcnvxf,sgl,dbl %0,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "8")]) - -(define_insn "floatsidf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (float:DF (match_operand:SI 1 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fcnvxf,sgl,dbl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -;; CYGNUS LOCAL pa8000/law */ -(define_expand "floatunssisf2" - [(set (subreg:SI (match_dup 2) 1) - (match_operand:SI 1 "register_operand" "")) - (set (subreg:SI (match_dup 2) 0) - (const_int 0)) - (set (match_operand:SF 0 "register_operand" "") - (float:SF (match_dup 2)))] - "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" - " -{ - if (TARGET_PARISC_2_0) - { - emit_insn (gen_floatunssisf2_pa20 (operands[0], operands[1])); - DONE; - } - operands[2] = gen_reg_rtx (DImode); -}") - -(define_expand "floatunssidf2" - [(set (subreg:SI (match_dup 2) 1) - (match_operand:SI 1 "register_operand" "")) - (set (subreg:SI (match_dup 2) 0) - (const_int 0)) - (set (match_operand:DF 0 "register_operand" "") - (float:DF (match_dup 2)))] - "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" - " -{ - if (TARGET_PARISC_2_0) - { - emit_insn (gen_floatunssidf2_pa20 (operands[0], operands[1])); - DONE; - } - operands[2] = gen_reg_rtx (DImode); -}") -;; END CYGNUS LOCAL - -(define_insn "floatdisf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (float:SF (match_operand:DI 1 "register_operand" "f")))] - "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" - "fcnvxf,dbl,sgl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "floatdidf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (float:DF (match_operand:DI 1 "register_operand" "f")))] - "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" - "fcnvxf,dbl,dbl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -;; Convert a float to an actual integer. -;; Truncation is performed as part of the conversion. - -(define_insn "fix_truncsfsi2" - [(set (match_operand:SI 0 "register_operand" "=f") - (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] - "! TARGET_SOFT_FLOAT" - "fcnvfxt,sgl,sgl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "fix_truncdfsi2" - [(set (match_operand:SI 0 "register_operand" "=f") - (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))] - "! TARGET_SOFT_FLOAT" - "fcnvfxt,dbl,sgl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "fix_truncsfdi2" - [(set (match_operand:DI 0 "register_operand" "=f") - (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] - "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" - "fcnvfxt,sgl,dbl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "fix_truncdfdi2" - [(set (match_operand:DI 0 "register_operand" "=f") - (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))] - "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" - "fcnvfxt,dbl,dbl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -;; CYGNUS LOCAL pa8000/law -(define_insn "floatunssidf2_pa20" - [(set (match_operand:DF 0 "register_operand" "=f") - (unsigned_float:DF (match_operand:SI 1 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fcnvuf,sgl,dbl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "floatunssisf2_pa20" - [(set (match_operand:SF 0 "register_operand" "=f") - (unsigned_float:SF (match_operand:SI 1 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fcnvuf,sgl,sgl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "floatunsdisf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (unsigned_float:SF (match_operand:DI 1 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fcnvuf,dbl,sgl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "floatunsdidf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (unsigned_float:DF (match_operand:DI 1 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fcnvuf,dbl,dbl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "fixuns_truncsfsi2" - [(set (match_operand:SI 0 "register_operand" "=f") - (unsigned_fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fcnvfut,sgl,sgl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "fixuns_truncdfsi2" - [(set (match_operand:SI 0 "register_operand" "=f") - (unsigned_fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fcnvfut,dbl,sgl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "fixuns_truncsfdi2" - [(set (match_operand:DI 0 "register_operand" "=f") - (unsigned_fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fcnvfut,sgl,dbl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "fixuns_truncdfdi2" - [(set (match_operand:DI 0 "register_operand" "=f") - (unsigned_fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fcnvfut,dbl,dbl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) -;; END CYGNUS LOCAL - -;;- arithmetic instructions - -(define_insn "adddi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (plus:DI (match_operand:DI 1 "register_operand" "%r") - (match_operand:DI 2 "arith11_operand" "rI")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - if (INTVAL (operands[2]) >= 0) - return \"addi %2,%R1,%R0\;addc %1,0,%0\"; - else - return \"addi %2,%R1,%R0\;subb %1,0,%0\"; - } - else - return \"add %R2,%R1,%R0\;addc %2,%1,%0\"; -}" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (not:SI (match_operand:SI 1 "register_operand" "r")) - (match_operand:SI 2 "register_operand" "r")))] - "" - "uaddcm %2,%1,%0" - [(set_attr "type" "binary") - (set_attr "length" "4")]) - -;; define_splits to optimize cases of adding a constant integer -;; to a register when the constant does not fit in 14 bits. */ -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" ""))) - (clobber (match_operand:SI 4 "register_operand" ""))] - "! cint_ok_for_move (INTVAL (operands[2])) - && VAL_14_BITS_P (INTVAL (operands[2]) >> 1)" - [(set (match_dup 4) (plus:SI (match_dup 1) (match_dup 2))) - (set (match_dup 0) (plus:SI (match_dup 4) (match_dup 3)))] - " -{ - int val = INTVAL (operands[2]); - int low = (val < 0) ? -0x2000 : 0x1fff; - int rest = val - low; - - operands[2] = GEN_INT (rest); - operands[3] = GEN_INT (low); -}") - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" ""))) - (clobber (match_operand:SI 4 "register_operand" ""))] - "! cint_ok_for_move (INTVAL (operands[2]))" - [(set (match_dup 4) (match_dup 2)) - (set (match_dup 0) (plus:SI (mult:SI (match_dup 4) (match_dup 3)) - (match_dup 1)))] - " -{ - HOST_WIDE_INT intval = INTVAL (operands[2]); - - /* Try dividing the constant by 2, then 4, and finally 8 to see - if we can get a constant which can be loaded into a register - in a single instruction (cint_ok_for_move). - - If that fails, try to negate the constant and subtract it - from our input operand. */ - if (intval % 2 == 0 && cint_ok_for_move (intval / 2)) - { - operands[2] = GEN_INT (intval / 2); - operands[3] = GEN_INT (2); - } - else if (intval % 4 == 0 && cint_ok_for_move (intval / 4)) - { - operands[2] = GEN_INT (intval / 4); - operands[3] = GEN_INT (4); - } - else if (intval % 8 == 0 && cint_ok_for_move (intval / 8)) - { - operands[2] = GEN_INT (intval / 8); - operands[3] = GEN_INT (8); - } - else if (cint_ok_for_move (-intval)) - { - emit_insn (gen_rtx_SET (VOIDmode, operands[4], GEN_INT (-intval))); - emit_insn (gen_subsi3 (operands[0], operands[1], operands[4])); - DONE; - } - else - FAIL; -}") - -(define_insn "addsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (plus:SI (match_operand:SI 1 "register_operand" "%r,r") - (match_operand:SI 2 "arith_operand" "r,J")))] - "" - "@ - addl %1,%2,%0 - ldo %2(%1),%0" - [(set_attr "type" "binary,binary") - (set_attr "pa_combine_type" "addmove") - (set_attr "length" "4,4")]) - -;; Disgusting kludge to work around reload bugs with frame pointer -;; elimination. Similar to other magic reload patterns in the -;; indexed memory operations. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=&r") - (plus:SI (plus:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "register_operand" "r")) - (match_operand:SI 3 "const_int_operand" "rL")))] - "reload_in_progress" - "* -{ - if (GET_CODE (operands[3]) == CONST_INT) - return \"ldo %3(%2),%0\;addl %1,%0,%0\"; - else - return \"addl %3,%2,%0\;addl %1,%0,%0\"; -}" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -(define_insn "subdi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (minus:DI (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "register_operand" "r")))] - "" - "sub %R1,%R2,%R0\;subb %1,%2,%0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -;; CYGNUS LOCAL PA8000/law -(define_expand "subsi3" - [(set (match_operand:SI 0 "register_operand" "") - (minus:SI (match_operand:SI 1 "arith11_operand" "") - (match_operand:SI 2 "register_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (minus:SI (match_operand:SI 1 "arith11_operand" "r,I") - (match_operand:SI 2 "register_operand" "r,r")))] - "!TARGET_PARISC_2_0" - "@ - sub %1,%2,%0 - subi %1,%2,%0" - [(set_attr "type" "binary,binary") - (set_attr "length" "4,4")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,q") - (minus:SI (match_operand:SI 1 "arith11_operand" "r,I,S") - (match_operand:SI 2 "register_operand" "r,r,r")))] - "TARGET_PARISC_2_0" - "@ - sub %1,%2,%0 - subi %1,%2,%0 - mtsarcm %2" - [(set_attr "type" "binary,binary,move") - (set_attr "length" "4,4,4")]) -;; END CYGNUS LOCAL - -;; Clobbering a "register_operand" instead of a match_scratch -;; in operand3 of millicode calls avoids spilling %r1 and -;; produces better code. - -;; The mulsi3 insns set up registers for the millicode call. -(define_expand "mulsi3" - [(set (reg:SI 26) (match_operand:SI 1 "move_operand" "")) - (set (reg:SI 25) (match_operand:SI 2 "move_operand" "")) - (parallel [(set (reg:SI 29) (mult:SI (reg:SI 26) (reg:SI 25))) - (clobber (match_dup 3)) - (clobber (reg:SI 26)) - (clobber (reg:SI 25)) - (clobber (reg:SI 31))]) - (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))] - "" - " -{ - if (TARGET_SNAKE && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT) - { - rtx scratch = gen_reg_rtx (DImode); - operands[1] = force_reg (SImode, operands[1]); - operands[2] = force_reg (SImode, operands[2]); - emit_insn (gen_umulsidi3 (scratch, operands[1], operands[2])); - emit_insn (gen_rtx_SET (VOIDmode, - operands[0], - gen_rtx_SUBREG (SImode, scratch, 1))); - DONE; - } - operands[3] = gen_reg_rtx (SImode); -}") - -(define_insn "umulsidi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "=f") - (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f")) - (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "f"))))] - "TARGET_SNAKE && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT" - "xmpyu %1,%2,%0" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:DI 0 "nonimmediate_operand" "=f") - (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f")) - (match_operand:DI 2 "uint32_operand" "f")))] - "TARGET_SNAKE && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT" - "xmpyu %1,%R2,%0" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "4")]) - -(define_insn "" - [(set (reg:SI 29) (mult:SI (reg:SI 26) (reg:SI 25))) - (clobber (match_operand:SI 0 "register_operand" "=a")) - (clobber (reg:SI 26)) - (clobber (reg:SI 25)) - (clobber (reg:SI 31))] - "" - "* return output_mul_insn (0, insn);" - [(set_attr "type" "milli") - (set (attr "length") - (cond [ -;; Target (or stub) within reach - (and (lt (plus (symbol_ref "total_code_bytes") (pc)) - (const_int 240000)) - (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0))) - (const_int 4) - -;; NO_SPACE_REGS - (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") - (const_int 0)) - (const_int 8) - -;; Out of reach, but not PIC or PORTABLE_RUNTIME -;; same as NO_SPACE_REGS code - (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0)) - (eq (symbol_ref "flag_pic") - (const_int 0))) - (const_int 8)] - -;; Out of range and either PIC or PORTABLE_RUNTIME - (const_int 24)))]) - -;;; Division and mod. -(define_expand "divsi3" - [(set (reg:SI 26) (match_operand:SI 1 "move_operand" "")) - (set (reg:SI 25) (match_operand:SI 2 "move_operand" "")) - (parallel [(set (reg:SI 29) (div:SI (reg:SI 26) (reg:SI 25))) - (clobber (match_dup 3)) - (clobber (reg:SI 26)) - (clobber (reg:SI 25)) - (clobber (reg:SI 31))]) - (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))] - "" - " -{ - operands[3] = gen_reg_rtx (SImode); - if (GET_CODE (operands[2]) == CONST_INT && emit_hpdiv_const (operands, 0)) - DONE; -}") - -(define_insn "" - [(set (reg:SI 29) - (div:SI (reg:SI 26) (match_operand:SI 0 "div_operand" ""))) - (clobber (match_operand:SI 1 "register_operand" "=a")) - (clobber (reg:SI 26)) - (clobber (reg:SI 25)) - (clobber (reg:SI 31))] - "" - "* - return output_div_insn (operands, 0, insn);" - [(set_attr "type" "milli") - (set (attr "length") - (cond [ -;; Target (or stub) within reach - (and (lt (plus (symbol_ref "total_code_bytes") (pc)) - (const_int 240000)) - (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0))) - (const_int 4) - -;; NO_SPACE_REGS - (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") - (const_int 0)) - (const_int 8) - -;; Out of reach, but not PIC or PORTABLE_RUNTIME -;; same as NO_SPACE_REGS code - (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0)) - (eq (symbol_ref "flag_pic") - (const_int 0))) - (const_int 8)] - -;; Out of range and either PIC or PORTABLE_RUNTIME - (const_int 24)))]) - -(define_expand "udivsi3" - [(set (reg:SI 26) (match_operand:SI 1 "move_operand" "")) - (set (reg:SI 25) (match_operand:SI 2 "move_operand" "")) - (parallel [(set (reg:SI 29) (udiv:SI (reg:SI 26) (reg:SI 25))) - (clobber (match_dup 3)) - (clobber (reg:SI 26)) - (clobber (reg:SI 25)) - (clobber (reg:SI 31))]) - (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))] - "" - " -{ - operands[3] = gen_reg_rtx (SImode); - if (GET_CODE (operands[2]) == CONST_INT && emit_hpdiv_const (operands, 1)) - DONE; -}") - -(define_insn "" - [(set (reg:SI 29) - (udiv:SI (reg:SI 26) (match_operand:SI 0 "div_operand" ""))) - (clobber (match_operand:SI 1 "register_operand" "=a")) - (clobber (reg:SI 26)) - (clobber (reg:SI 25)) - (clobber (reg:SI 31))] - "" - "* - return output_div_insn (operands, 1, insn);" - [(set_attr "type" "milli") - (set (attr "length") - (cond [ -;; Target (or stub) within reach - (and (lt (plus (symbol_ref "total_code_bytes") (pc)) - (const_int 240000)) - (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0))) - (const_int 4) - -;; NO_SPACE_REGS - (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") - (const_int 0)) - (const_int 8) - -;; Out of reach, but not PIC or PORTABLE_RUNTIME -;; same as NO_SPACE_REGS code - (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0)) - (eq (symbol_ref "flag_pic") - (const_int 0))) - (const_int 8)] - -;; Out of range and either PIC or PORTABLE_RUNTIME - (const_int 24)))]) - -(define_expand "modsi3" - [(set (reg:SI 26) (match_operand:SI 1 "move_operand" "")) - (set (reg:SI 25) (match_operand:SI 2 "move_operand" "")) - (parallel [(set (reg:SI 29) (mod:SI (reg:SI 26) (reg:SI 25))) - (clobber (match_dup 3)) - (clobber (reg:SI 26)) - (clobber (reg:SI 25)) - (clobber (reg:SI 31))]) - (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))] - "" - " -{ - operands[3] = gen_reg_rtx (SImode); -}") - -(define_insn "" - [(set (reg:SI 29) (mod:SI (reg:SI 26) (reg:SI 25))) - (clobber (match_operand:SI 0 "register_operand" "=a")) - (clobber (reg:SI 26)) - (clobber (reg:SI 25)) - (clobber (reg:SI 31))] - "" - "* - return output_mod_insn (0, insn);" - [(set_attr "type" "milli") - (set (attr "length") - (cond [ -;; Target (or stub) within reach - (and (lt (plus (symbol_ref "total_code_bytes") (pc)) - (const_int 240000)) - (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0))) - (const_int 4) - -;; NO_SPACE_REGS - (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") - (const_int 0)) - (const_int 8) - -;; Out of reach, but not PIC or PORTABLE_RUNTIME -;; same as NO_SPACE_REGS code - (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0)) - (eq (symbol_ref "flag_pic") - (const_int 0))) - (const_int 8)] - -;; Out of range and either PIC or PORTABLE_RUNTIME - (const_int 24)))]) - -(define_expand "umodsi3" - [(set (reg:SI 26) (match_operand:SI 1 "move_operand" "")) - (set (reg:SI 25) (match_operand:SI 2 "move_operand" "")) - (parallel [(set (reg:SI 29) (umod:SI (reg:SI 26) (reg:SI 25))) - (clobber (match_dup 3)) - (clobber (reg:SI 26)) - (clobber (reg:SI 25)) - (clobber (reg:SI 31))]) - (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))] - "" - " -{ - operands[3] = gen_reg_rtx (SImode); -}") - -(define_insn "" - [(set (reg:SI 29) (umod:SI (reg:SI 26) (reg:SI 25))) - (clobber (match_operand:SI 0 "register_operand" "=a")) - (clobber (reg:SI 26)) - (clobber (reg:SI 25)) - (clobber (reg:SI 31))] - "" - "* - return output_mod_insn (1, insn);" - [(set_attr "type" "milli") - (set (attr "length") - (cond [ -;; Target (or stub) within reach - (and (lt (plus (symbol_ref "total_code_bytes") (pc)) - (const_int 240000)) - (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0))) - (const_int 4) - -;; NO_SPACE_REGS - (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") - (const_int 0)) - (const_int 8) - -;; Out of reach, but not PIC or PORTABLE_RUNTIME -;; same as NO_SPACE_REGS code - (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0)) - (eq (symbol_ref "flag_pic") - (const_int 0))) - (const_int 8)] - -;; Out of range and either PIC or PORTABLE_RUNTIME - (const_int 24)))]) - -;;- and instructions -;; We define DImode `and` so with DImode `not` we can get -;; DImode `andn`. Other combinations are possible. - -(define_expand "anddi3" - [(set (match_operand:DI 0 "register_operand" "") - (and:DI (match_operand:DI 1 "arith_double_operand" "") - (match_operand:DI 2 "arith_double_operand" "")))] - "" - " -{ - if (! register_operand (operands[1], DImode) - || ! register_operand (operands[2], DImode)) - /* Let GCC break this into word-at-a-time operations. */ - FAIL; -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (and:DI (match_operand:DI 1 "register_operand" "%r") - (match_operand:DI 2 "register_operand" "r")))] - "" - "and %1,%2,%0\;and %R1,%R2,%R0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -; The ? for op1 makes reload prefer zdepi instead of loading a huge -; constant with ldil;ldo. -(define_insn "andsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (and:SI (match_operand:SI 1 "register_operand" "%?r,0") - (match_operand:SI 2 "and_operand" "rO,P")))] - "" - "* return output_and (operands); " - [(set_attr "type" "binary,shift") - (set_attr "length" "4,4")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (and:DI (not:DI (match_operand:DI 1 "register_operand" "r")) - (match_operand:DI 2 "register_operand" "r")))] - "" - "andcm %2,%1,%0\;andcm %R2,%R1,%R0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (not:SI (match_operand:SI 1 "register_operand" "r")) - (match_operand:SI 2 "register_operand" "r")))] - "" - "andcm %2,%1,%0" - [(set_attr "type" "binary") - (set_attr "length" "4")]) - -(define_expand "iordi3" - [(set (match_operand:DI 0 "register_operand" "") - (ior:DI (match_operand:DI 1 "arith_double_operand" "") - (match_operand:DI 2 "arith_double_operand" "")))] - "" - " -{ - if (! register_operand (operands[1], DImode) - || ! register_operand (operands[2], DImode)) - /* Let GCC break this into word-at-a-time operations. */ - FAIL; -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (ior:DI (match_operand:DI 1 "register_operand" "%r") - (match_operand:DI 2 "register_operand" "r")))] - "" - "or %1,%2,%0\;or %R1,%R2,%R0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -;; Need a define_expand because we've run out of CONST_OK... characters. -(define_expand "iorsi3" - [(set (match_operand:SI 0 "register_operand" "") - (ior:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "arith32_operand" "")))] - "" - " -{ - if (! (ior_operand (operands[2], SImode) - || register_operand (operands[2], SImode))) - operands[2] = force_reg (SImode, operands[2]); -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (ior:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "ior_operand" "M,i")))] - "" - "* return output_ior (operands); " - [(set_attr "type" "binary,shift") - (set_attr "length" "4,4")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "register_operand" "r")))] - "" - "or %1,%2,%0" - [(set_attr "type" "binary") - (set_attr "length" "4")]) - -(define_expand "xordi3" - [(set (match_operand:DI 0 "register_operand" "") - (xor:DI (match_operand:DI 1 "arith_double_operand" "") - (match_operand:DI 2 "arith_double_operand" "")))] - "" - " -{ - if (! register_operand (operands[1], DImode) - || ! register_operand (operands[2], DImode)) - /* Let GCC break this into word-at-a-time operations. */ - FAIL; -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (xor:DI (match_operand:DI 1 "register_operand" "%r") - (match_operand:DI 2 "register_operand" "r")))] - "" - "xor %1,%2,%0\;xor %R1,%R2,%R0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -(define_insn "xorsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (xor:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "register_operand" "r")))] - "" - "xor %1,%2,%0" - [(set_attr "type" "binary") - (set_attr "length" "4")]) - -(define_insn "negdi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (neg:DI (match_operand:DI 1 "register_operand" "r")))] - "" - "sub 0,%R1,%R0\;subb 0,%1,%0" - [(set_attr "type" "unary") - (set_attr "length" "8")]) - -(define_insn "negsi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (neg:SI (match_operand:SI 1 "register_operand" "r")))] - "" - "sub 0,%1,%0" - [(set_attr "type" "unary") - (set_attr "length" "4")]) - -(define_expand "one_cmpldi2" - [(set (match_operand:DI 0 "register_operand" "") - (not:DI (match_operand:DI 1 "arith_double_operand" "")))] - "" - " -{ - if (! register_operand (operands[1], DImode)) - FAIL; -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (not:DI (match_operand:DI 1 "register_operand" "r")))] - "" - "uaddcm 0,%1,%0\;uaddcm 0,%R1,%R0" - [(set_attr "type" "unary") - (set_attr "length" "8")]) - -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (not:SI (match_operand:SI 1 "register_operand" "r")))] - "" - "uaddcm 0,%1,%0" - [(set_attr "type" "unary") - (set_attr "length" "4")]) - -;; Floating point arithmetic instructions. - -(define_insn "adddf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (plus:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fadd,dbl %1,%2,%0" - [(set_attr "type" "fpalu") - (set_attr "pa_combine_type" "faddsub") - (set_attr "length" "4")]) - -(define_insn "addsf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (plus:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fadd,sgl %1,%2,%0" - [(set_attr "type" "fpalu") - (set_attr "pa_combine_type" "faddsub") - (set_attr "length" "4")]) - -(define_insn "subdf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (minus:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fsub,dbl %1,%2,%0" - [(set_attr "type" "fpalu") - (set_attr "pa_combine_type" "faddsub") - (set_attr "length" "4")]) - -(define_insn "subsf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (minus:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fsub,sgl %1,%2,%0" - [(set_attr "type" "fpalu") - (set_attr "pa_combine_type" "faddsub") - (set_attr "length" "4")]) - -(define_insn "muldf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (mult:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fmpy,dbl %1,%2,%0" - [(set_attr "type" "fpmuldbl") - (set_attr "pa_combine_type" "fmpy") - (set_attr "length" "4")]) - -(define_insn "mulsf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fmpy,sgl %1,%2,%0" - [(set_attr "type" "fpmulsgl") - (set_attr "pa_combine_type" "fmpy") - (set_attr "length" "4")]) - -(define_insn "divdf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (div:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fdiv,dbl %1,%2,%0" - [(set_attr "type" "fpdivdbl") - (set_attr "length" "4")]) - -(define_insn "divsf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (div:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fdiv,sgl %1,%2,%0" - [(set_attr "type" "fpdivsgl") - (set_attr "length" "4")]) - -;; CYGNUS LOCAL pa8000/law -(define_insn "negdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (match_operand:DF 1 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "* -{ - if (TARGET_PARISC_2_0) - return \"fneg,dbl %1,%0\"; - return \"fsub,dbl 0,%1,%0\"; -}" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "negsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (match_operand:SF 1 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "* -{ - if (TARGET_PARISC_2_0) - return \"fneg,sgl %1,%0\"; - return \"fsub,sgl 0,%1,%0\"; -}" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) -;; END CYGNUS LOCAL - -(define_insn "absdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (abs:DF (match_operand:DF 1 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fabs,dbl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "abssf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (abs:SF (match_operand:SF 1 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fabs,sgl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -;; CYGNUS LOCAL pa8000/law -;; Simple fused multiply-add sequences. -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")) - (match_operand:DF 3 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fmpyfadd,dbl %1,%2,%3,%0" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")) - (match_operand:SF 3 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fmpyfadd,sgl %1,%2,%3,%0" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "4")]) - -;; Generating a fused multiply sequence is a win for this case as it will -;; reduce the latency for the fused case without impacting the plain -;; multiply case. -;; -;; Similar possibilities exist for fnegabs, shadd and other insns which -;; perform two operations with the result of the first feeding the second. -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")) - (match_operand:DF 3 "register_operand" "f"))) - (set (match_operand:DF 4 "register_operand" "=&f") - (mult:DF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "#" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "8")]) - -;; We want to split this up during scheduling since we want both insns -;; to schedule independently. -(define_split - [(set (match_operand:DF 0 "register_operand" "=f") - (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")) - (match_operand:DF 3 "register_operand" "f"))) - (set (match_operand:DF 4 "register_operand" "=&f") - (mult:DF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - [(set (match_dup 4) (mult:DF (match_dup 1) (match_dup 2))) - (set (match_dup 0) (plus:DF (mult:DF (match_dup 1) (match_dup 2)) - (match_dup 3)))] - "") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")) - (match_operand:SF 3 "register_operand" "f"))) - (set (match_operand:SF 4 "register_operand" "=&f") - (mult:SF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "#" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "8")]) - -;; We want to split this up during scheduling since we want both insns -;; to schedule independently. -(define_split - [(set (match_operand:SF 0 "register_operand" "=f") - (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")) - (match_operand:SF 3 "register_operand" "f"))) - (set (match_operand:SF 4 "register_operand" "=&f") - (mult:SF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - [(set (match_dup 4) (mult:SF (match_dup 1) (match_dup 2))) - (set (match_dup 0) (plus:SF (mult:SF (match_dup 1) (match_dup 2)) - (match_dup 3)))] - "") - -;; Negating a multiply can be faked by adding zero in a fused multiply-add -;; instruction. -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (mult:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f"))))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fmpynfadd,dbl %1,%2,0,%0" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f"))))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fmpynfadd,sgl %1,%2,0,%0" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (mult:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))) - (set (match_operand:DF 3 "register_operand" "=&f") - (mult:DF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "#" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (mult:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))) - (set (match_operand:DF 3 "register_operand" "=&f") - (mult:DF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - [(set (match_dup 3) (mult:DF (match_dup 1) (match_dup 2))) - (set (match_dup 0) (neg:DF (mult:DF (match_dup 1) (match_dup 2))))] - "") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))) - (set (match_operand:SF 3 "register_operand" "=&f") - (mult:SF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "#" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))) - (set (match_operand:SF 3 "register_operand" "=&f") - (mult:SF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - [(set (match_dup 3) (mult:SF (match_dup 1) (match_dup 2))) - (set (match_dup 0) (neg:SF (mult:SF (match_dup 1) (match_dup 2))))] - "") - -;; Now fused multiplies with the result of the multiply negated. -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (plus:DF (neg:DF (mult:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f"))) - (match_operand:DF 3 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fmpynfadd,dbl %1,%2,%3,%0" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (plus:SF (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f"))) - (match_operand:SF 3 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fmpynfadd,sgl %1,%2,%3,%0" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (plus:DF (neg:DF (mult:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f"))) - (match_operand:DF 3 "register_operand" "f"))) - (set (match_operand:DF 4 "register_operand" "=&f") - (mult:DF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "#" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:DF 0 "register_operand" "=f") - (plus:DF (neg:DF (mult:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f"))) - (match_operand:DF 3 "register_operand" "f"))) - (set (match_operand:DF 4 "register_operand" "=&f") - (mult:DF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - [(set (match_dup 4) (mult:DF (match_dup 1) (match_dup 2))) - (set (match_dup 0) (plus:DF (neg:DF (mult:DF (match_dup 1) (match_dup 2))) - (match_dup 3)))] - "") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (plus:SF (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f"))) - (match_operand:SF 3 "register_operand" "f"))) - (set (match_operand:SF 4 "register_operand" "=&f") - (mult:SF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "#" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:SF 0 "register_operand" "=f") - (plus:SF (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f"))) - (match_operand:SF 3 "register_operand" "f"))) - (set (match_operand:SF 4 "register_operand" "=&f") - (mult:SF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - [(set (match_dup 4) (mult:SF (match_dup 1) (match_dup 2))) - (set (match_dup 0) (plus:SF (neg:SF (mult:SF (match_dup 1) (match_dup 2))) - (match_dup 3)))] - "") - -;; Same thing, but using minus instead of negation -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (minus:DF (match_operand:DF 3 "register_operand" "f") - (mult:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f"))))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fmpynfadd,dbl %1,%2,%3,%0" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (minus:SF (match_operand:SF 3 "register_operand" "f") - (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f"))))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fmpynfadd,sgl %1,%2,%3,%0" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (minus:DF (match_operand:DF 3 "register_operand" "f") - (mult:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))) - (set (match_operand:DF 4 "register_operand" "=&f") - (mult:DF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "#" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:DF 0 "register_operand" "=f") - (minus:DF (match_operand:DF 3 "register_operand" "f") - (mult:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))) - (set (match_operand:DF 4 "register_operand" "=&f") - (mult:DF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - [(set (match_dup 4) (mult:DF (match_dup 1) (match_dup 2))) - (set (match_dup 0) (minus:DF (match_dup 3) - (mult:DF (match_dup 1) (match_dup 2))))] - "") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (minus:SF (match_operand:SF 3 "register_operand" "f") - (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))) - (set (match_operand:SF 4 "register_operand" "=&f") - (mult:SF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "#" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:SF 0 "register_operand" "=f") - (minus:SF (match_operand:SF 3 "register_operand" "f") - (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))) - (set (match_operand:SF 4 "register_operand" "=&f") - (mult:SF (match_dup 1) (match_dup 2)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - [(set (match_dup 4) (mult:SF (match_dup 1) (match_dup 2))) - (set (match_dup 0) (minus:SF (match_dup 3) - (mult:SF (match_dup 1) (match_dup 2))))] - "") - -;; And similarly for negation of an absolute value. -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (abs:DF (match_operand:DF 1 "register_operand" "f"))))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fnegabs,dbl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (abs:SF (match_operand:SF 1 "register_operand" "f"))))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "fnegabs,sgl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (abs:DF (match_operand:DF 1 "register_operand" "f")))) - (set (match_operand:DF 2 "register_operand" "=&f") (abs:DF (match_dup 1)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "#" - [(set_attr "type" "fpalu") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (abs:DF (match_operand:DF 1 "register_operand" "f")))) - (set (match_operand:DF 2 "register_operand" "=&f") (abs:DF (match_dup 1)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - [(set (match_dup 2) (abs:DF (match_dup 1))) - (set (match_dup 0) (neg:DF (abs:DF (match_dup 1))))] - "") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (abs:SF (match_operand:SF 1 "register_operand" "f")))) - (set (match_operand:SF 2 "register_operand" "=&f") (abs:SF (match_dup 1)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - "#" - [(set_attr "type" "fpalu") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (abs:SF (match_operand:SF 1 "register_operand" "f")))) - (set (match_operand:SF 2 "register_operand" "=&f") (abs:SF (match_dup 1)))] - "! TARGET_SOFT_FLOAT && TARGET_PARISC_2_0" - [(set (match_dup 2) (abs:SF (match_dup 1))) - (set (match_dup 0) (neg:SF (abs:SF (match_dup 1))))] - "") - -;; END CYGNUS LOCAL - -(define_insn "sqrtdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (sqrt:DF (match_operand:DF 1 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fsqrt,dbl %1,%0" - [(set_attr "type" "fpsqrtdbl") - (set_attr "length" "4")]) - -(define_insn "sqrtsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (sqrt:SF (match_operand:SF 1 "register_operand" "f")))] - "! TARGET_SOFT_FLOAT" - "fsqrt,sgl %1,%0" - [(set_attr "type" "fpsqrtsgl") - (set_attr "length" "4")]) - -;;- Shift instructions - -;; Optimized special case of shifting. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") - (const_int 24)))] - "" - "ldb%M1 %1,%0" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") - (const_int 16)))] - "" - "ldh%M1 %1,%0" - [(set_attr "type" "load") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "shadd_operand" "")) - (match_operand:SI 1 "register_operand" "r")))] - "" - "sh%O3addl %2,%1,%0" - [(set_attr "type" "binary") - (set_attr "length" "4")]) - -;; This variant of the above insn can occur if the first operand -;; is the frame pointer. This is a kludge, but there doesn't -;; seem to be a way around it. Only recognize it while reloading. -;; Note how operand 3 uses a predicate of "const_int_operand", but -;; has constraints allowing a register. I don't know how this works, -;; but it somehow makes sure that out-of-range constants are placed -;; in a register which somehow magically is a "const_int_operand". -;; (this was stolen from alpha.md, I'm not going to try and change it. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=&r,r") - (plus:SI (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r,r") - (match_operand:SI 4 "shadd_operand" "")) - (match_operand:SI 1 "register_operand" "r,r")) - (match_operand:SI 3 "const_int_operand" "r,J")))] - "reload_in_progress" - "@ - sh%O4addl %2,%1,%0\;addl %3,%0,%0 - sh%O4addl %2,%1,%0\;ldo %3(%0),%0" - [(set_attr "type" "multi") - (set_attr "length" "8")]) - -;; This anonymous pattern and splitter wins because it reduces the latency -;; of the shadd sequence without increasing the latency of the shift. -;; -;; We want to make sure and split up the operations for the scheduler since -;; these instructions can (and should) schedule independently. -;; -;; It would be clearer if combine used the same operator for both expressions, -;; it's somewhat confusing to have a mult in ine operation and an ashift -;; in the other. -;; -;; If this pattern is not split before register allocation, then we must expose -;; the fact that operand 4 is set before operands 1, 2 and 3 have been read. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "shadd_operand" "")) - (match_operand:SI 1 "register_operand" "r"))) - (set (match_operand:SI 4 "register_operand" "=&r") - (ashift:SI (match_dup 2) - (match_operand:SI 5 "const_int_operand" "i")))] - "INTVAL (operands[5]) == exact_log2 (INTVAL (operands[3]))" - "#" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "shadd_operand" "")) - (match_operand:SI 1 "register_operand" "r"))) - (set (match_operand:SI 4 "register_operand" "=&r") - (ashift:SI (match_dup 2) - (match_operand:SI 5 "const_int_operand" "i")))] - "INTVAL (operands[5]) == exact_log2 (INTVAL (operands[3]))" - [(set (match_dup 4) (ashift:SI (match_dup 2) (match_dup 5))) - (set (match_dup 0) (plus:SI (mult:SI (match_dup 2) (match_dup 3)) - (match_dup 1)))] - "") - -(define_expand "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "") - (ashift:SI (match_operand:SI 1 "lhs_lshift_operand" "") - (match_operand:SI 2 "arith32_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - { - rtx temp = gen_reg_rtx (SImode); - emit_insn (gen_subsi3 (temp, GEN_INT (31), operands[2])); - if (GET_CODE (operands[1]) == CONST_INT) - emit_insn (gen_zvdep_imm (operands[0], operands[1], temp)); - else - emit_insn (gen_zvdep32 (operands[0], operands[1], temp)); - DONE; - } - /* Make sure both inputs are not constants, - there are no patterns for that. */ - operands[1] = force_reg (SImode, operands[1]); -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashift:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "const_int_operand" "n")))] - "" - "zdep %1,%P2,%L2,%0" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -; Match cases of op1 a CONST_INT here that zvdep_imm doesn't handle. -; Doing it like this makes slightly better code since reload can -; replace a register with a known value in range -16..15 with a -; constant. Ideally, we would like to merge zvdep32 and zvdep_imm, -; but since we have no more CONST_OK... characters, that is not -; possible. -(define_insn "zvdep32" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (ashift:SI (match_operand:SI 1 "arith5_operand" "r,L") - (minus:SI (const_int 31) - (match_operand:SI 2 "register_operand" "q,q"))))] - "" - "@ - zvdep %1,32,%0 - zvdepi %1,32,%0" - [(set_attr "type" "shift,shift") - (set_attr "length" "4,4")]) - -(define_insn "zvdep_imm" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashift:SI (match_operand:SI 1 "lhs_lshift_cint_operand" "") - (minus:SI (const_int 31) - (match_operand:SI 2 "register_operand" "q"))))] - "" - "* -{ - int x = INTVAL (operands[1]); - operands[2] = GEN_INT (4 + exact_log2 ((x >> 4) + 1)); - operands[1] = GEN_INT ((x & 0xf) - 0x10); - return \"zvdepi %1,%2,%0\"; -}" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -(define_insn "vdepi_ior" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "") - (minus:SI (const_int 31) - (match_operand:SI 2 "register_operand" "q"))) - (match_operand:SI 3 "register_operand" "0")))] - ; accept ...0001...1, can this be generalized? - "exact_log2 (INTVAL (operands[1]) + 1) >= 0" - "* -{ - int x = INTVAL (operands[1]); - operands[2] = GEN_INT (exact_log2 (x + 1)); - return \"vdepi -1,%2,%0\"; -}" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -(define_insn "vdepi_and" - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (rotate:SI (match_operand:SI 1 "const_int_operand" "") - (minus:SI (const_int 31) - (match_operand:SI 2 "register_operand" "q"))) - (match_operand:SI 3 "register_operand" "0")))] - ; this can be generalized...! - "INTVAL (operands[1]) == -2" - "* -{ - int x = INTVAL (operands[1]); - operands[2] = GEN_INT (exact_log2 ((~x) + 1)); - return \"vdepi 0,%2,%0\"; -}" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -(define_expand "ashrsi3" - [(set (match_operand:SI 0 "register_operand" "") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "arith32_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - { - rtx temp = gen_reg_rtx (SImode); - emit_insn (gen_subsi3 (temp, GEN_INT (31), operands[2])); - emit_insn (gen_vextrs32 (operands[0], operands[1], temp)); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "const_int_operand" "n")))] - "" - "extrs %1,%P2,%L2,%0" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -(define_insn "vextrs32" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") - (minus:SI (const_int 31) - (match_operand:SI 2 "register_operand" "q"))))] - "" - "vextrs %1,32,%0" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r") - (match_operand:SI 2 "arith32_operand" "q,n")))] - "" - "@ - vshd 0,%1,%0 - extru %1,%P2,%L2,%0" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -(define_insn "rotrsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (rotatert:SI (match_operand:SI 1 "register_operand" "r,r") - (match_operand:SI 2 "arith32_operand" "q,n")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - operands[2] = GEN_INT (INTVAL (operands[2]) & 31); - return \"shd %1,%1,%2,%0\"; - } - else - return \"vshd %1,%1,%0\"; -}" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 5 "plus_xor_ior_operator" - [(ashift:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 3 "const_int_operand" "n")) - (lshiftrt:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 4 "const_int_operand" "n"))]))] - "INTVAL (operands[3]) + INTVAL (operands[4]) == 32" - "shd %1,%2,%4,%0" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 5 "plus_xor_ior_operator" - [(lshiftrt:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 4 "const_int_operand" "n")) - (ashift:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 3 "const_int_operand" "n"))]))] - "INTVAL (operands[3]) + INTVAL (operands[4]) == 32" - "shd %1,%2,%4,%0" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "const_int_operand" "")) - (match_operand:SI 3 "const_int_operand" "")))] - "exact_log2 (1 + (INTVAL (operands[3]) >> (INTVAL (operands[2]) & 31))) >= 0" - "* -{ - int cnt = INTVAL (operands[2]) & 31; - operands[3] = GEN_INT (exact_log2 (1 + (INTVAL (operands[3]) >> cnt))); - operands[2] = GEN_INT (31 - cnt); - return \"zdep %1,%2,%3,%0\"; -}" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -;; Unconditional and other jump instructions. - -;; CYGNUS LOCAL PA8000/law -(define_insn "return" - [(return)] - "hppa_can_use_return_insn_p ()" - "* -{ - if (TARGET_PARISC_2_0) - return \"bve%* 0(%%r2)\"; - return \"bv%* 0(%%r2)\"; -}" - [(set_attr "type" "branch") - (set_attr "length" "4")]) - -;; Use a different pattern for functions which have non-trivial -;; epilogues so as not to confuse jump and reorg. -(define_insn "return_internal" - [(use (reg:SI 2)) - (return)] - "" - "* -{ - if (TARGET_PARISC_2_0) - return \"bve%* 0(%%r2)\"; - return \"bv%* 0(%%r2)\"; -}" - [(set_attr "type" "branch") - (set_attr "length" "4")]) -;; END CYGNUS LOCAL - -(define_expand "prologue" - [(const_int 0)] - "" - "hppa_expand_prologue ();DONE;") - -(define_expand "epilogue" - [(return)] - "" - " -{ - /* Try to use the trivial return first. Else use the full - epilogue. */ - if (hppa_can_use_return_insn_p ()) - emit_jump_insn (gen_return ()); - else - { - hppa_expand_epilogue (); - emit_jump_insn (gen_return_internal ()); - } - DONE; -}") - -;; Special because we use the value placed in %r2 by the bl instruction -;; from within its delay slot to set the value for the 2nd parameter to -;; the call. -(define_insn "call_profiler" - [(unspec_volatile [(const_int 0)] 0) - (use (match_operand:SI 0 "const_int_operand" ""))] - "" - "bl _mcount,%%r2\;ldo %0(%%r2),%%r25" - [(set_attr "type" "multi") - (set_attr "length" "8")]) - -(define_insn "blockage" - [(unspec_volatile [(const_int 2)] 0)] - "" - "" - [(set_attr "length" "0")]) - -(define_insn "jump" - [(set (pc) (label_ref (match_operand 0 "" "")))] - "" - "* -{ - extern int optimize; - - if (GET_MODE (insn) == SImode) - return \"bl %l0,0%#\"; - - /* An unconditional branch which can reach its target. */ - if (get_attr_length (insn) != 24 - && get_attr_length (insn) != 16) - return \"bl%* %l0,0\"; - - /* An unconditional branch which can not reach its target. - - We need to be able to use %r1 as a scratch register; however, - we can never be sure whether or not it's got a live value in - it. Therefore, we must restore its original value after the - jump. - - To make matters worse, we don't have a stack slot which we - can always clobber. sp-12/sp-16 shouldn't ever have a live - value during a non-optimizing compilation, so we use those - slots for now. We don't support very long branches when - optimizing -- they should be quite rare when optimizing. - - Really the way to go long term is a register scavenger; goto - the target of the jump and find a register which we can use - as a scratch to hold the value in %r1. */ - - /* We don't know how to register scavenge yet. */ - if (optimize) - abort (); - - /* First store %r1 into the stack. */ - output_asm_insn (\"stw %%r1,-16(%%r30)\", operands); - - /* Now load the target address into %r1 and do an indirect jump - to the value specified in %r1. Be careful to generate PIC - code as needed. */ - if (flag_pic) - { - rtx xoperands[2]; - xoperands[0] = operands[0]; - xoperands[1] = gen_label_rtx (); - - output_asm_insn (\"bl .+8,%%r1\\n\\taddil L'%l0-%l1,%%r1\", xoperands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", - CODE_LABEL_NUMBER (xoperands[1])); - output_asm_insn (\"ldo R'%l0-%l1(%%r1),%%r1\\n\\tbv 0(%%r1)\", - xoperands); - } - else - output_asm_insn (\"ldil L'%l0,%%r1\\n\\tbe R'%l0(%%sr4,%%r1)\", operands);; - - /* And restore the value of %r1 in the delay slot. We're not optimizing, - so we know nothing else can be in the delay slot. */ - return \"ldw -16(%%r30),%%r1\"; -}" - [(set_attr "type" "uncond_branch") - (set_attr "pa_combine_type" "uncond_branch") - (set (attr "length") - (cond [(eq (symbol_ref "jump_in_call_delay (insn)") (const_int 1)) - (if_then_else (lt (abs (minus (match_dup 0) - (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)) - (ge (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) - (const_int 262100)) - (if_then_else (eq (symbol_ref "flag_pic") (const_int 0)) - (const_int 16) - (const_int 24))] - (const_int 4)))]) - -;; Subroutines of "casesi". -;; operand 0 is index -;; operand 1 is the minimum bound -;; operand 2 is the maximum bound - minimum bound + 1 -;; operand 3 is CODE_LABEL for the table; -;; operand 4 is the CODE_LABEL to go to if index out of range. - -(define_expand "casesi" - [(match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "const_int_operand" "") - (match_operand:SI 2 "const_int_operand" "") - (match_operand 3 "" "") - (match_operand 4 "" "")] - "" - " -{ - if (GET_CODE (operands[0]) != REG) - operands[0] = force_reg (SImode, operands[0]); - - if (operands[1] != const0_rtx) - { - rtx reg = gen_reg_rtx (SImode); - - operands[1] = GEN_INT (-INTVAL (operands[1])); - if (!INT_14_BITS (operands[1])) - operands[1] = force_reg (SImode, operands[1]); - emit_insn (gen_addsi3 (reg, operands[0], operands[1])); - - operands[0] = reg; - } - - if (!INT_5_BITS (operands[2])) - operands[2] = force_reg (SImode, operands[2]); - - emit_insn (gen_cmpsi (operands[0], operands[2])); - emit_jump_insn (gen_bgtu (operands[4])); - if (TARGET_BIG_SWITCH) - { - rtx temp = gen_reg_rtx (SImode); - emit_move_insn (temp, gen_rtx_PLUS (SImode, operands[0], operands[0])); - operands[0] = temp; - } - emit_jump_insn (gen_casesi0 (operands[0], operands[3])); - DONE; -}") - -(define_insn "casesi0" - [(set (pc) (plus:SI - (mem:SI (plus:SI (pc) - (match_operand:SI 0 "register_operand" "r"))) - (label_ref (match_operand 1 "" ""))))] - "" - "blr %0,0\;nop" - [(set_attr "type" "multi") - (set_attr "length" "8")]) - -;; Need nops for the calls because execution is supposed to continue -;; past; we don't want to nullify an instruction that we need. -;;- jump to subroutine - -(define_expand "call" - [(parallel [(call (match_operand:SI 0 "" "") - (match_operand 1 "" "")) - (clobber (reg:SI 2))])] - "" - " -{ - rtx op; - rtx call_insn; - - if (TARGET_PORTABLE_RUNTIME) - op = force_reg (SImode, XEXP (operands[0], 0)); - else - op = XEXP (operands[0], 0); - - /* Use two different patterns for calls to explicitly named functions - and calls through function pointers. This is necessary as these two - types of calls use different calling conventions, and CSE might try - to change the named call into an indirect call in some cases (using - two patterns keeps CSE from performing this optimization). */ - if (GET_CODE (op) == SYMBOL_REF) - call_insn = emit_call_insn (gen_call_internal_symref (op, operands[1])); - else - { - rtx tmpreg = gen_rtx_REG (SImode, 22); - emit_move_insn (tmpreg, force_reg (SImode, op)); - call_insn = emit_call_insn (gen_call_internal_reg (operands[1])); - } - - if (flag_pic) - { - use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), pic_offset_table_rtx); - - /* After each call we must restore the PIC register, even if it - doesn't appear to be used. - - This will set regs_ever_live for the callee saved register we - stored the PIC register in. */ - emit_move_insn (pic_offset_table_rtx, - gen_rtx_REG (SImode, PIC_OFFSET_TABLE_REGNUM_SAVED)); - emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx)); - - /* Gross. We have to keep the scheduler from moving the restore - of the PIC register away from the call. SCHED_GROUP_P is - supposed to do this, but for some reason the compiler will - go into an infinite loop when we use that. - - This method (blockage insn) may make worse code (then again - it may not since calls are nearly blockages anyway), but at - least it should work. */ - emit_insn (gen_blockage ()); - } - DONE; -}") - -(define_insn "call_internal_symref" - [(call (mem:SI (match_operand:SI 0 "call_operand_address" "")) - (match_operand 1 "" "i")) - (clobber (reg:SI 2)) - (use (const_int 0))] - "! TARGET_PORTABLE_RUNTIME" - "* -{ - output_arg_descriptor (insn); - return output_call (insn, operands[0], gen_rtx_REG (SImode, 2)); -}" - [(set_attr "type" "call") - (set (attr "length") -;; If we're sure that we can either reach the target or that the -;; linker can use a long-branch stub, then the length is 4 bytes. -;; -;; For long-calls the length will be either 52 bytes (non-pic) -;; or 68 bytes (pic). */ -;; Else we have to use a long-call; - (if_then_else (lt (plus (symbol_ref "total_code_bytes") (pc)) - (const_int 240000)) - (const_int 4) - (if_then_else (eq (symbol_ref "flag_pic") - (const_int 0)) - (const_int 52) - (const_int 68))))]) - -(define_insn "call_internal_reg" - [(call (mem:SI (reg:SI 22)) - (match_operand 0 "" "i")) - (clobber (reg:SI 2)) - (use (const_int 1))] - "" - "* -{ - rtx xoperands[2]; - - /* First the special case for kernels, level 0 systems, etc. */ - if (TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS) - return \"ble 0(%%sr4,%%r22)\;copy %%r31,%%r2\"; - - /* Now the normal case -- we can reach $$dyncall directly or - we're sure that we can get there via a long-branch stub. - - No need to check target flags as the length uniquely identifies - the remaining cases. */ - if (get_attr_length (insn) == 8) - return \".CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2\"; - - /* Long millicode call, but we are not generating PIC or portable runtime - code. */ - if (get_attr_length (insn) == 12) - return \".CALL\\tARGW0=GR\;ldil L%%$$dyncall,%%r2\;ble R%%$$dyncall(%%sr4,%%r2)\;copy %%r31,%%r2\"; - - /* Long millicode call for portable runtime. */ - if (get_attr_length (insn) == 20) - return \"ldil L%%$$dyncall,%%r31\;ldo R%%$$dyncall(%%r31),%%r31\;blr 0,%%r2\;bv,n 0(%%r31)\;nop\"; - - /* If we're generating PIC code. */ - xoperands[0] = operands[0]; - xoperands[1] = gen_label_rtx (); - output_asm_insn (\"bl .+8,%%r1\", xoperands); - output_asm_insn (\"addil L%%$$dyncall-%1,%%r1\", xoperands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", - CODE_LABEL_NUMBER (xoperands[1])); - output_asm_insn (\"ldo R%%$$dyncall-%1(%%r1),%%r1\", xoperands); - output_asm_insn (\"blr 0,%%r2\", xoperands); - output_asm_insn (\"bv,n 0(%%r1)\\n\\tnop\", xoperands); - return \"\"; -}" - [(set_attr "type" "dyncall") - (set (attr "length") - (cond [ -;; First NO_SPACE_REGS - (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") - (const_int 0)) - (const_int 8) - -;; Target (or stub) within reach - (and (lt (plus (symbol_ref "total_code_bytes") (pc)) - (const_int 240000)) - (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0))) - (const_int 8) - -;; Out of reach, but not PIC or PORTABLE_RUNTIME - (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0)) - (eq (symbol_ref "flag_pic") - (const_int 0))) - (const_int 12) - - (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0)) - (const_int 20)] - -;; Out of range PIC case - (const_int 24)))]) - -(define_expand "call_value" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand:SI 1 "" "") - (match_operand 2 "" ""))) - (clobber (reg:SI 2))])] - "" - " -{ - rtx op; - rtx call_insn; - - if (TARGET_PORTABLE_RUNTIME) - op = force_reg (SImode, XEXP (operands[1], 0)); - else - op = XEXP (operands[1], 0); - - /* Use two different patterns for calls to explicitly named functions - and calls through function pointers. This is necessary as these two - types of calls use different calling conventions, and CSE might try - to change the named call into an indirect call in some cases (using - two patterns keeps CSE from performing this optimization). */ - if (GET_CODE (op) == SYMBOL_REF) - call_insn = emit_call_insn (gen_call_value_internal_symref (operands[0], - op, - operands[2])); - else - { - rtx tmpreg = gen_rtx_REG (SImode, 22); - emit_move_insn (tmpreg, force_reg (SImode, op)); - call_insn = emit_call_insn (gen_call_value_internal_reg (operands[0], - operands[2])); - } - if (flag_pic) - { - use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), pic_offset_table_rtx); - - /* After each call we must restore the PIC register, even if it - doesn't appear to be used. - - This will set regs_ever_live for the callee saved register we - stored the PIC register in. */ - emit_move_insn (pic_offset_table_rtx, - gen_rtx_REG (SImode, PIC_OFFSET_TABLE_REGNUM_SAVED)); - emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx)); - - /* Gross. We have to keep the scheduler from moving the restore - of the PIC register away from the call. SCHED_GROUP_P is - supposed to do this, but for some reason the compiler will - go into an infinite loop when we use that. - - This method (blockage insn) may make worse code (then again - it may not since calls are nearly blockages anyway), but at - least it should work. */ - emit_insn (gen_blockage ()); - } - DONE; -}") - -(define_insn "call_value_internal_symref" - [(set (match_operand 0 "" "=rf") - (call (mem:SI (match_operand:SI 1 "call_operand_address" "")) - (match_operand 2 "" "i"))) - (clobber (reg:SI 2)) - (use (const_int 0))] - ;;- Don't use operand 1 for most machines. - "! TARGET_PORTABLE_RUNTIME" - "* -{ - output_arg_descriptor (insn); - return output_call (insn, operands[1], gen_rtx_REG (SImode, 2)); -}" - [(set_attr "type" "call") - (set (attr "length") -;; If we're sure that we can either reach the target or that the -;; linker can use a long-branch stub, then the length is 4 bytes. -;; -;; For long-calls the length will be either 52 bytes (non-pic) -;; or 68 bytes (pic). */ -;; Else we have to use a long-call; - (if_then_else (lt (plus (symbol_ref "total_code_bytes") (pc)) - (const_int 240000)) - (const_int 4) - (if_then_else (eq (symbol_ref "flag_pic") - (const_int 0)) - (const_int 52) - (const_int 68))))]) - -(define_insn "call_value_internal_reg" - [(set (match_operand 0 "" "=rf") - (call (mem:SI (reg:SI 22)) - (match_operand 1 "" "i"))) - (clobber (reg:SI 2)) - (use (const_int 1))] - "" - "* -{ - rtx xoperands[2]; - - /* First the special case for kernels, level 0 systems, etc. */ - if (TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS) - return \"ble 0(%%sr4,%%r22)\;copy %%r31,%%r2\"; - - /* Now the normal case -- we can reach $$dyncall directly or - we're sure that we can get there via a long-branch stub. - - No need to check target flags as the length uniquely identifies - the remaining cases. */ - if (get_attr_length (insn) == 8) - return \".CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2\"; - - /* Long millicode call, but we are not generating PIC or portable runtime - code. */ - if (get_attr_length (insn) == 12) - return \".CALL\\tARGW0=GR\;ldil L%%$$dyncall,%%r2\;ble R%%$$dyncall(%%sr4,%%r2)\;copy %%r31,%%r2\"; - - /* Long millicode call for portable runtime. */ - if (get_attr_length (insn) == 20) - return \"ldil L%%$$dyncall,%%r31\;ldo R%%$$dyncall(%%r31),%%r31\;blr 0,%%r2\;bv,n 0(%%r31)\;nop\"; - - /* If we're generating PIC code. */ - xoperands[0] = operands[1]; - xoperands[1] = gen_label_rtx (); - output_asm_insn (\"bl .+8,%%r1\", xoperands); - output_asm_insn (\"addil L%%$$dyncall-%1,%%r1\", xoperands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", - CODE_LABEL_NUMBER (xoperands[1])); - output_asm_insn (\"ldo R%%$$dyncall-%1(%%r1),%%r1\", xoperands); - output_asm_insn (\"blr 0,%%r2\", xoperands); - output_asm_insn (\"bv,n 0(%%r1)\\n\\tnop\", xoperands); - return \"\"; -}" - [(set_attr "type" "dyncall") - (set (attr "length") - (cond [ -;; First NO_SPACE_REGS - (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") - (const_int 0)) - (const_int 8) - -;; Target (or stub) within reach - (and (lt (plus (symbol_ref "total_code_bytes") (pc)) - (const_int 240000)) - (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0))) - (const_int 8) - -;; Out of reach, but not PIC or PORTABLE_RUNTIME - (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0)) - (eq (symbol_ref "flag_pic") - (const_int 0))) - (const_int 12) - - (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0)) - (const_int 20)] - -;; Out of range PIC case - (const_int 24)))]) - -;; Call subroutine returning any type. - -(define_expand "untyped_call" - [(parallel [(call (match_operand 0 "" "") - (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] - "" - " -{ - int i; - - emit_call_insn (gen_call (operands[0], const0_rtx)); - - for (i = 0; i < XVECLEN (operands[2], 0); i++) - { - rtx set = XVECEXP (operands[2], 0, i); - emit_move_insn (SET_DEST (set), SET_SRC (set)); - } - - /* The optimizer does not know that the call sets the function value - registers we stored in the result block. We avoid problems by - claiming that all hard registers are used and clobbered at this - point. */ - emit_insn (gen_blockage ()); - - DONE; -}") -(define_insn "nop" - [(const_int 0)] - "" - "nop" - [(set_attr "type" "move") - (set_attr "length" "4")]) - -;; These are just placeholders so we know where branch tables -;; begin and end. -(define_insn "begin_brtab" - [(const_int 1)] - "" - "* -{ - /* Only GAS actually supports this pseudo-op. */ - if (TARGET_GAS) - return \".begin_brtab\"; - else - return \"\"; -}" - [(set_attr "type" "move") - (set_attr "length" "0")]) - -(define_insn "end_brtab" - [(const_int 2)] - "" - "* -{ - /* Only GAS actually supports this pseudo-op. */ - if (TARGET_GAS) - return \".end_brtab\"; - else - return \"\"; -}" - [(set_attr "type" "move") - (set_attr "length" "0")]) - -;;; Hope this is only within a function... -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "register_operand" "r"))] - "" - "bv%* 0(%0)" - [(set_attr "type" "branch") - (set_attr "length" "4")]) - -(define_insn "extzv" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extract:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "uint5_operand" "") - (match_operand:SI 3 "uint5_operand" "")))] - "" - "extru %1,%3+%2-1,%2,%0" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extract:SI (match_operand:SI 1 "register_operand" "r") - (const_int 1) - (match_operand:SI 3 "register_operand" "q")))] - "" - "vextru %1,1,%0" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -(define_insn "extv" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extract:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "uint5_operand" "") - (match_operand:SI 3 "uint5_operand" "")))] - "" - "extrs %1,%3+%2-1,%2,%0" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extract:SI (match_operand:SI 1 "register_operand" "r") - (const_int 1) - (match_operand:SI 3 "register_operand" "q")))] - "" - "vextrs %1,1,%0" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -(define_insn "insv" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r,r") - (match_operand:SI 1 "uint5_operand" "") - (match_operand:SI 2 "uint5_operand" "")) - (match_operand:SI 3 "arith5_operand" "r,L"))] - "" - "@ - dep %3,%2+%1-1,%1,%0 - depi %3,%2+%1-1,%1,%0" - [(set_attr "type" "shift,shift") - (set_attr "length" "4,4")]) - -;; Optimize insertion of const_int values of type 1...1xxxx. -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") - (match_operand:SI 1 "uint5_operand" "") - (match_operand:SI 2 "uint5_operand" "")) - (match_operand:SI 3 "const_int_operand" ""))] - "(INTVAL (operands[3]) & 0x10) != 0 && - (~INTVAL (operands[3]) & ((1L << INTVAL (operands[1])) - 1) & ~0xf) == 0" - "* -{ - operands[3] = GEN_INT ((INTVAL (operands[3]) & 0xf) - 0x10); - return \"depi %3,%2+%1-1,%1,%0\"; -}" - [(set_attr "type" "shift") - (set_attr "length" "4")]) - -;; This insn is used for some loop tests, typically loops reversed when -;; strength reduction is used. It is actually created when the instruction -;; combination phase combines the special loop test. Since this insn -;; is both a jump insn and has an output, it must deal with its own -;; reloads, hence the `m' constraints. The `!' constraints direct reload -;; to not choose the register alternatives in the event a reload is needed. -(define_insn "decrement_and_branch_until_zero" - [(set (pc) - (if_then_else - (match_operator 2 "comparison_operator" - [(plus:SI (match_operand:SI 0 "register_operand" "+!r,!*f,!*m") - (match_operand:SI 1 "int5_operand" "L,L,L")) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) (match_dup 1))) - (clobber (match_scratch:SI 4 "=X,r,r"))] - "" - "* return output_dbra (operands, insn, which_alternative); " -;; Do not expect to understand this the first time through. -[(set_attr "type" "cbranch,multi,multi") - (set (attr "length") - (if_then_else (eq_attr "alternative" "0") -;; Loop counter in register case -;; Short branch has length of 4 -;; Long branch has length of 8 - (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)) - -;; Loop counter in FP reg case. -;; Extra goo to deal with additional reload insns. - (if_then_else (eq_attr "alternative" "1") - (if_then_else (lt (match_dup 3) (pc)) - (if_then_else - (lt (abs (minus (match_dup 3) (plus (pc) (const_int 24)))) - (const_int 8184)) - (const_int 24) - (const_int 28)) - (if_then_else - (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 24) - (const_int 28))) -;; Loop counter in memory case. -;; Extra goo to deal with additional reload insns. - (if_then_else (lt (match_dup 3) (pc)) - (if_then_else - (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12)))) - (const_int 8184)) - (const_int 12) - (const_int 16)) - (if_then_else - (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 12) - (const_int 16))))))]) - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 2 "movb_comparison_operator" - [(match_operand:SI 1 "register_operand" "r,r,r,r") (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc))) - (set (match_operand:SI 0 "register_operand" "=!r,!*f,!*m,!*q") - (match_dup 1))] - "" -"* return output_movb (operands, insn, which_alternative, 0); " -;; Do not expect to understand this the first time through. -[(set_attr "type" "cbranch,multi,multi,multi") - (set (attr "length") - (if_then_else (eq_attr "alternative" "0") -;; Loop counter in register case -;; Short branch has length of 4 -;; Long branch has length of 8 - (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)) - -;; Loop counter in FP reg case. -;; Extra goo to deal with additional reload insns. - (if_then_else (eq_attr "alternative" "1") - (if_then_else (lt (match_dup 3) (pc)) - (if_then_else - (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12)))) - (const_int 8184)) - (const_int 12) - (const_int 16)) - (if_then_else - (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 12) - (const_int 16))) -;; Loop counter in memory or sar case. -;; Extra goo to deal with additional reload insns. - (if_then_else - (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 8) - (const_int 12)))))]) - -;; Handle negated branch. -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 2 "movb_comparison_operator" - [(match_operand:SI 1 "register_operand" "r,r,r,r") (const_int 0)]) - (pc) - (label_ref (match_operand 3 "" "")))) - (set (match_operand:SI 0 "register_operand" "=!r,!*f,!*m,!*q") - (match_dup 1))] - "" -"* return output_movb (operands, insn, which_alternative, 1); " -;; Do not expect to understand this the first time through. -[(set_attr "type" "cbranch,multi,multi,multi") - (set (attr "length") - (if_then_else (eq_attr "alternative" "0") -;; Loop counter in register case -;; Short branch has length of 4 -;; Long branch has length of 8 - (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)) - -;; Loop counter in FP reg case. -;; Extra goo to deal with additional reload insns. - (if_then_else (eq_attr "alternative" "1") - (if_then_else (lt (match_dup 3) (pc)) - (if_then_else - (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12)))) - (const_int 8184)) - (const_int 12) - (const_int 16)) - (if_then_else - (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 12) - (const_int 16))) -;; Loop counter in memory or SAR case. -;; Extra goo to deal with additional reload insns. - (if_then_else - (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 8) - (const_int 12)))))]) - -;; The next several patterns (parallel_addb, parallel_movb, fmpyadd and -;; fmpysub aren't currently used by the FSF sources, but will be soon. -;; -;; They're in the FSF tree for documentation and to make Cygnus<->FSF -;; merging easier. -(define_insn "" - [(set (pc) (label_ref (match_operand 3 "" "" ))) - (set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "ireg_or_int5_operand" "rL")))] - "(reload_completed && operands[0] == operands[1]) || operands[0] == operands[2]" - "* -{ - return output_parallel_addb (operands, get_attr_length (insn)); -}" - [(set_attr "type" "parallel_branch") - (set (attr "length") - (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)))]) - -(define_insn "" - [(set (pc) (label_ref (match_operand 2 "" "" ))) - (set (match_operand:SF 0 "register_operand" "=r") - (match_operand:SF 1 "ireg_or_int5_operand" "rL"))] - "reload_completed" - "* -{ - return output_parallel_movb (operands, get_attr_length (insn)); -}" - [(set_attr "type" "parallel_branch") - (set (attr "length") - (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)))]) - -(define_insn "" - [(set (pc) (label_ref (match_operand 2 "" "" ))) - (set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "ireg_or_int5_operand" "rL"))] - "reload_completed" - "* -{ - return output_parallel_movb (operands, get_attr_length (insn)); -}" - [(set_attr "type" "parallel_branch") - (set (attr "length") - (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)))]) - -(define_insn "" - [(set (pc) (label_ref (match_operand 2 "" "" ))) - (set (match_operand:HI 0 "register_operand" "=r") - (match_operand:HI 1 "ireg_or_int5_operand" "rL"))] - "reload_completed" - "* -{ - return output_parallel_movb (operands, get_attr_length (insn)); -}" - [(set_attr "type" "parallel_branch") - (set (attr "length") - (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)))]) - -(define_insn "" - [(set (pc) (label_ref (match_operand 2 "" "" ))) - (set (match_operand:QI 0 "register_operand" "=r") - (match_operand:QI 1 "ireg_or_int5_operand" "rL"))] - "reload_completed" - "* -{ - return output_parallel_movb (operands, get_attr_length (insn)); -}" - [(set_attr "type" "parallel_branch") - (set (attr "length") - (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) - (const_int 8184)) - (const_int 4) - (const_int 8)))]) - -(define_insn "" - [(set (match_operand 0 "register_operand" "=f") - (mult (match_operand 1 "register_operand" "f") - (match_operand 2 "register_operand" "f"))) - (set (match_operand 3 "register_operand" "+f") - (plus (match_operand 4 "register_operand" "f") - (match_operand 5 "register_operand" "f")))] - "TARGET_SNAKE && ! TARGET_SOFT_FLOAT - && reload_completed && fmpyaddoperands (operands)" - "* -{ - if (GET_MODE (operands[0]) == DFmode) - { - if (rtx_equal_p (operands[3], operands[5])) - return \"fmpyadd,dbl %1,%2,%0,%4,%3\"; - else - return \"fmpyadd,dbl %1,%2,%0,%5,%3\"; - } - else - { - if (rtx_equal_p (operands[3], operands[5])) - return \"fmpyadd,sgl %1,%2,%0,%4,%3\"; - else - return \"fmpyadd,sgl %1,%2,%0,%5,%3\"; - } -}" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand 3 "register_operand" "+f") - (plus (match_operand 4 "register_operand" "f") - (match_operand 5 "register_operand" "f"))) - (set (match_operand 0 "register_operand" "=f") - (mult (match_operand 1 "register_operand" "f") - (match_operand 2 "register_operand" "f")))] - "TARGET_SNAKE && ! TARGET_SOFT_FLOAT - && reload_completed && fmpyaddoperands (operands)" - "* -{ - if (GET_MODE (operands[0]) == DFmode) - { - if (rtx_equal_p (operands[3], operands[5])) - return \"fmpyadd,dbl %1,%2,%0,%4,%3\"; - else - return \"fmpyadd,dbl %1,%2,%0,%5,%3\"; - } - else - { - if (rtx_equal_p (operands[3], operands[5])) - return \"fmpyadd,sgl %1,%2,%0,%4,%3\"; - else - return \"fmpyadd,sgl %1,%2,%0,%5,%3\"; - } -}" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand 0 "register_operand" "=f") - (mult (match_operand 1 "register_operand" "f") - (match_operand 2 "register_operand" "f"))) - (set (match_operand 3 "register_operand" "+f") - (minus (match_operand 4 "register_operand" "f") - (match_operand 5 "register_operand" "f")))] - "TARGET_SNAKE && ! TARGET_SOFT_FLOAT - && reload_completed && fmpysuboperands (operands)" - "* -{ - if (GET_MODE (operands[0]) == DFmode) - return \"fmpysub,dbl %1,%2,%0,%5,%3\"; - else - return \"fmpysub,sgl %1,%2,%0,%5,%3\"; -}" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand 3 "register_operand" "+f") - (minus (match_operand 4 "register_operand" "f") - (match_operand 5 "register_operand" "f"))) - (set (match_operand 0 "register_operand" "=f") - (mult (match_operand 1 "register_operand" "f") - (match_operand 2 "register_operand" "f")))] - "TARGET_SNAKE && ! TARGET_SOFT_FLOAT - && reload_completed && fmpysuboperands (operands)" - "* -{ - if (GET_MODE (operands[0]) == DFmode) - return \"fmpysub,dbl %1,%2,%0,%5,%3\"; - else - return \"fmpysub,sgl %1,%2,%0,%5,%3\"; -}" - [(set_attr "type" "fpalu") - (set_attr "length" "4")]) - -;; Clean up turds left by reload. -(define_peephole - [(set (match_operand 0 "reg_or_nonsymb_mem_operand" "") - (match_operand 1 "register_operand" "fr")) - (set (match_operand 2 "register_operand" "fr") - (match_dup 0))] - "! TARGET_SOFT_FLOAT - && GET_CODE (operands[0]) == MEM - && ! MEM_VOLATILE_P (operands[0]) - && GET_MODE (operands[0]) == GET_MODE (operands[1]) - && GET_MODE (operands[0]) == GET_MODE (operands[2]) - && GET_MODE (operands[0]) == DFmode - && GET_CODE (operands[1]) == REG - && GET_CODE (operands[2]) == REG - && ! side_effects_p (XEXP (operands[0], 0)) - && REGNO_REG_CLASS (REGNO (operands[1])) - == REGNO_REG_CLASS (REGNO (operands[2]))" - "* -{ - rtx xoperands[2]; - - if (FP_REG_P (operands[1])) - output_asm_insn (output_fp_move_double (operands), operands); - else - output_asm_insn (output_move_double (operands), operands); - - if (rtx_equal_p (operands[1], operands[2])) - return \"\"; - - xoperands[0] = operands[2]; - xoperands[1] = operands[1]; - - if (FP_REG_P (xoperands[1])) - output_asm_insn (output_fp_move_double (xoperands), xoperands); - else - output_asm_insn (output_move_double (xoperands), xoperands); - - return \"\"; -}") - -(define_peephole - [(set (match_operand 0 "register_operand" "fr") - (match_operand 1 "reg_or_nonsymb_mem_operand" "")) - (set (match_operand 2 "register_operand" "fr") - (match_dup 1))] - "! TARGET_SOFT_FLOAT - && GET_CODE (operands[1]) == MEM - && ! MEM_VOLATILE_P (operands[1]) - && GET_MODE (operands[0]) == GET_MODE (operands[1]) - && GET_MODE (operands[0]) == GET_MODE (operands[2]) - && GET_MODE (operands[0]) == DFmode - && GET_CODE (operands[0]) == REG - && GET_CODE (operands[2]) == REG - && ! side_effects_p (XEXP (operands[1], 0)) - && REGNO_REG_CLASS (REGNO (operands[0])) - == REGNO_REG_CLASS (REGNO (operands[2]))" - "* -{ - rtx xoperands[2]; - - if (FP_REG_P (operands[0])) - output_asm_insn (output_fp_move_double (operands), operands); - else - output_asm_insn (output_move_double (operands), operands); - - xoperands[0] = operands[2]; - xoperands[1] = operands[0]; - - if (FP_REG_P (xoperands[1])) - output_asm_insn (output_fp_move_double (xoperands), xoperands); - else - output_asm_insn (output_move_double (xoperands), xoperands); - - return \"\"; -}") - -;; Flush the I and D cache line found at the address in operand 0. -;; This is used by the trampoline code for nested functions. -;; So long as the trampoline itself is less than 32 bytes this -;; is sufficient. - -(define_insn "dcacheflush" - [(unspec_volatile [(const_int 1)] 0) - (use (mem:SI (match_operand:SI 0 "register_operand" "r"))) - (use (mem:SI (match_operand:SI 1 "register_operand" "r")))] - "" - "fdc 0(0,%0)\;fdc 0(0,%1)\;sync" - [(set_attr "type" "multi") - (set_attr "length" "12")]) - -(define_insn "icacheflush" - [(unspec_volatile [(const_int 2)] 0) - (use (mem:SI (match_operand:SI 0 "register_operand" "r"))) - (use (mem:SI (match_operand:SI 1 "register_operand" "r"))) - (use (match_operand:SI 2 "register_operand" "r")) - (clobber (match_operand:SI 3 "register_operand" "=&r")) - (clobber (match_operand:SI 4 "register_operand" "=&r"))] - "" - "mfsp %%sr0,%4\;ldsid (0,%2),%3\;mtsp %3,%%sr0\;fic 0(%%sr0,%0)\;fic 0(%%sr0,%1)\;sync\;mtsp %4,%%sr0\;nop\;nop\;nop\;nop\;nop\;nop" - [(set_attr "type" "multi") - (set_attr "length" "52")]) - -;; An out-of-line prologue. -(define_insn "outline_prologue_call" - [(unspec_volatile [(const_int 0)] 0) - (clobber (reg:SI 31)) - (clobber (reg:SI 22)) - (clobber (reg:SI 21)) - (clobber (reg:SI 20)) - (clobber (reg:SI 19)) - (clobber (reg:SI 1))] - "" - "* -{ - extern int frame_pointer_needed; - - /* We need two different versions depending on whether or not we - need a frame pointer. Also note that we return to the instruction - immediately after the branch rather than two instructions after the - break as normally is the case. */ - if (frame_pointer_needed) - { - /* Must import the magic millicode routine(s). */ - output_asm_insn (\".IMPORT __outline_prologue_fp,MILLICODE\", NULL); - - if (TARGET_PORTABLE_RUNTIME) - { - output_asm_insn (\"ldil L'__outline_prologue_fp,%%r31\", NULL); - output_asm_insn (\"ble,n R'__outline_prologue_fp(%%sr0,%%r31)\", - NULL); - } - else - output_asm_insn (\"bl,n __outline_prologue_fp,%%r31\", NULL); - } - else - { - /* Must import the magic millicode routine(s). */ - output_asm_insn (\".IMPORT __outline_prologue,MILLICODE\", NULL); - - if (TARGET_PORTABLE_RUNTIME) - { - output_asm_insn (\"ldil L'__outline_prologue,%%r31\", NULL); - output_asm_insn (\"ble,n R'__outline_prologue(%%sr0,%%r31)\", NULL); - } - else - output_asm_insn (\"bl,n __outline_prologue,%%r31\", NULL); - } - return \"\"; -}" - [(set_attr "type" "multi") - (set_attr "length" "8")]) - -;; An out-of-line epilogue. -(define_insn "outline_epilogue_call" - [(unspec_volatile [(const_int 1)] 0) - (use (reg:SI 29)) - (use (reg:SI 28)) - (clobber (reg:SI 31)) - (clobber (reg:SI 22)) - (clobber (reg:SI 21)) - (clobber (reg:SI 20)) - (clobber (reg:SI 19)) - (clobber (reg:SI 2)) - (clobber (reg:SI 1))] - "" - "* -{ - extern int frame_pointer_needed; - - /* We need two different versions depending on whether or not we - need a frame pointer. Also note that we return to the instruction - immediately after the branch rather than two instructions after the - break as normally is the case. */ - if (frame_pointer_needed) - { - /* Must import the magic millicode routine. */ - output_asm_insn (\".IMPORT __outline_epilogue_fp,MILLICODE\", NULL); - - /* The out-of-line prologue will make sure we return to the right - instruction. */ - if (TARGET_PORTABLE_RUNTIME) - { - output_asm_insn (\"ldil L'__outline_epilogue_fp,%%r31\", NULL); - output_asm_insn (\"ble,n R'__outline_epilogue_fp(%%sr0,%%r31)\", - NULL); - } - else - output_asm_insn (\"bl,n __outline_epilogue_fp,%%r31\", NULL); - } - else - { - /* Must import the magic millicode routine. */ - output_asm_insn (\".IMPORT __outline_epilogue,MILLICODE\", NULL); - - /* The out-of-line prologue will make sure we return to the right - instruction. */ - if (TARGET_PORTABLE_RUNTIME) - { - output_asm_insn (\"ldil L'__outline_epilogue,%%r31\", NULL); - output_asm_insn (\"ble,n R'__outline_epilogue(%%sr0,%%r31)\", NULL); - } - else - output_asm_insn (\"bl,n __outline_epilogue,%%r31\", NULL); - } - return \"\"; -}" - [(set_attr "type" "multi") - (set_attr "length" "8")]) - -;; Given a function pointer, canonicalize it so it can be -;; reliably compared to another function pointer. */ -(define_expand "canonicalize_funcptr_for_compare" - [(set (reg:SI 26) (match_operand:SI 1 "register_operand" "")) - (parallel [(set (reg:SI 29) (unspec:SI [(reg:SI 26)] 0)) - (clobber (match_dup 2)) - (clobber (reg:SI 26)) - (clobber (reg:SI 22)) - (clobber (reg:SI 31))]) - (set (match_operand:SI 0 "register_operand" "") - (reg:SI 29))] - "! TARGET_PORTABLE_RUNTIME" - " -{ - operands[2] = gen_reg_rtx (SImode); - if (GET_CODE (operands[1]) != REG) - { - rtx tmp = gen_reg_rtx (Pmode); - emit_move_insn (tmp, operands[1]); - operands[1] = tmp; - } -}") - -(define_insn "" - [(set (reg:SI 29) (unspec:SI [(reg:SI 26)] 0)) - (clobber (match_operand:SI 0 "register_operand" "=a")) - (clobber (reg:SI 26)) - (clobber (reg:SI 22)) - (clobber (reg:SI 31))] - "" - "* -{ - /* Must import the magic millicode routine. */ - output_asm_insn (\".IMPORT $$sh_func_adrs,MILLICODE\", NULL); - - /* This is absolutely amazing. - - First, copy our input parameter into %r29 just in case we don't - need to call $$sh_func_adrs. */ - output_asm_insn (\"copy %%r26,%%r29\", NULL); - - /* Next, examine the low two bits in %r26, if they aren't 0x2, then - we use %r26 unchanged. */ - if (get_attr_length (insn) == 32) - output_asm_insn (\"extru %%r26,31,2,%%r31\;comib,<>,n 2,%%r31,.+24\", NULL); - else if (get_attr_length (insn) == 40) - output_asm_insn (\"extru %%r26,31,2,%%r31\;comib,<>,n 2,%%r31,.+32\", NULL); - else if (get_attr_length (insn) == 44) - output_asm_insn (\"extru %%r26,31,2,%%r31\;comib,<>,n 2,%%r31,.+36\", NULL); - else - output_asm_insn (\"extru %%r26,31,2,%%r31\;comib,<>,n 2,%%r31,.+20\", NULL); - - /* Next, compare %r26 with 4096, if %r26 is less than or equal to - 4096, then we use %r26 unchanged. */ - if (get_attr_length (insn) == 32) - output_asm_insn (\"ldi 4096,%%r31\;comb,<<,n %%r26,%%r31,.+16\", NULL); - else if (get_attr_length (insn) == 40) - output_asm_insn (\"ldi 4096,%%r31\;comb,<<,n %%r26,%%r31,.+24\", NULL); - else if (get_attr_length (insn) == 44) - output_asm_insn (\"ldi 4096,%%r31\;comb,<<,n %%r26,%%r31,.+28\", NULL); - else - output_asm_insn (\"ldi 4096,%%r31\;comb,<<,n %%r26,%%r31,.+12\", NULL); - - /* Else call $$sh_func_adrs to extract the function's real add24. */ - return output_millicode_call (insn, - gen_rtx_SYMBOL_REF (SImode, \"$$sh_func_adrs\")); -}" - [(set_attr "type" "multi") - (set (attr "length") - (cond [ -;; Target (or stub) within reach - (and (lt (plus (symbol_ref "total_code_bytes") (pc)) - (const_int 240000)) - (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0))) - (const_int 28) - -;; NO_SPACE_REGS - (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") - (const_int 0)) - (const_int 32) - -;; Out of reach, but not PIC or PORTABLE_RUNTIME -;; same as NO_SPACE_REGS code - (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0)) - (eq (symbol_ref "flag_pic") - (const_int 0))) - (const_int 32) - -;; PORTABLE_RUNTIME - (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") - (const_int 0)) - (const_int 40)] - -;; Out of range and PIC - (const_int 44)))]) - -;; On the PA, the PIC register is call clobbered, so it must -;; be saved & restored around calls by the caller. If the call -;; doesn't return normally (nonlocal goto, or an exception is -;; thrown), then the code at the exception handler label must -;; restore the PIC register. -(define_expand "exception_receiver" - [(const_int 4)] - "!TARGET_PORTABLE_RUNTIME && flag_pic" - " -{ - /* Load the PIC register from the stack slot (in our caller's - frame). */ - emit_move_insn (pic_offset_table_rtx, - gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, -32))); - emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx)); - emit_insn (gen_blockage ()); - DONE; -}") - - diff --git a/gcc/config/pa/pa1.h b/gcc/config/pa/pa1.h deleted file mode 100755 index 418de75..0000000 --- a/gcc/config/pa/pa1.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Definitions of target machine for GNU compiler, for HP PA-RISC 1.1 - Copyright (C) 1991 Free Software Foundation, Inc. - Contributed by Tim Moore (moore@defmacro.cs.utah.edu) - -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. */ - -#define TARGET_DEFAULT 0x89 /* TARGET_SNAKE + TARGET_GAS - + TARGET_JUMP_IN_DELAY */ - -/* This is the same as pa.h, except that we generate snake code by - default. */ - -#include "pa/pa.h" diff --git a/gcc/config/pa/rtems.h b/gcc/config/pa/rtems.h deleted file mode 100755 index a0d5b7a..0000000 --- a/gcc/config/pa/rtems.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Definitions of target machine for GNU compiler, for PRO. - Copyright (C) 1997 Free Software Foundation, Inc. - Contributed by Joel Sherrill (joel@OARcorp.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. */ - -/* Specify predefined symbols in preprocessor. */ - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dhppa -DPWB -Acpu(hppa) -Amachine(hppa) \ - -Drtems -D__rtems__ -Asystem(rtems)" - -/* Generate calls to memcpy, memcmp and memset. */ -#ifndef TARGET_MEM_FUNCTIONS -#define TARGET_MEM_FUNCTIONS -#endif diff --git a/gcc/config/pa/t-dce-thr b/gcc/config/pa/t-dce-thr deleted file mode 100755 index 8d86a41..0000000 --- a/gcc/config/pa/t-dce-thr +++ /dev/null @@ -1,5 +0,0 @@ -MULTILIB_OPTIONS = threads -MULTILIB_DIRNAMES = threads - -LIBGCC = stmp-multilib -INSTALL_LIBGCC = install-multilib diff --git a/gcc/config/pa/t-pa b/gcc/config/pa/t-pa deleted file mode 100755 index a359918..0000000 --- a/gcc/config/pa/t-pa +++ /dev/null @@ -1,18 +0,0 @@ -LIBGCC1=libgcc1.null -CROSS_LIBGCC1=libgcc1.null -ADA_CFLAGS=-mdisable-indexing -LIB2FUNCS_EXTRA=lib2funcs.asm ee.asm ee_fp.asm - -lib2funcs.asm: $(srcdir)/config/pa/lib2funcs.asm - rm -f lib2funcs.asm - cp $(srcdir)/config/pa/lib2funcs.asm . - -ee.asm: $(srcdir)/config/pa/ee.asm - rm -f ee.asm - cp $(srcdir)/config/pa/ee.asm . - -ee_fp.asm: $(srcdir)/config/pa/ee_fp.asm - rm -f ee_fp.asm - cp $(srcdir)/config/pa/ee_fp.asm . - -TARGET_LIBGCC2_CFLAGS = -fPIC diff --git a/gcc/config/pa/t-pro b/gcc/config/pa/t-pro deleted file mode 100755 index f40b2e4..0000000 --- a/gcc/config/pa/t-pro +++ /dev/null @@ -1,38 +0,0 @@ -LIBGCC1=libgcc1.null -CROSS_LIBGCC1 = libgcc1.null -LIB1ASMSRC = -LIB1ASMFUNCS = - -LIBGCC1_TEST = - -ADA_CFLAGS=-mdisable-indexing - -LIB2FUNCS_EXTRA=fp-bit.c dp-bit.c lib2funcs.asm ee.asm ee_fp.asm - -dp-bit.c: $(srcdir)/config/fp-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 - cat $(srcdir)/config/fp-bit.c >> fp-bit.c - -lib2funcs.asm: $(srcdir)/config/pa/lib2funcs.asm - rm -f lib2funcs.asm - cp $(srcdir)/config/pa/lib2funcs.asm . - -ee.asm: $(srcdir)/config/pa/ee.asm - rm -f ee.asm - cp $(srcdir)/config/pa/ee.asm . - -ee_fp.asm: $(srcdir)/config/pa/ee_fp.asm - rm -f ee_fp.asm - cp $(srcdir)/config/pa/ee_fp.asm . - -# Build the libraries for both speed and space optimizations - -MULTILIB_OPTIONS=mspace -MULTILIB_DIRNAMES=space -MULTILIB_MATCHES= - -LIBGCC = stmp-multilib -INSTALL_LIBGCC = install-multilib diff --git a/gcc/config/pa/x-pa b/gcc/config/pa/x-pa deleted file mode 100755 index 4c25047..0000000 --- a/gcc/config/pa/x-pa +++ /dev/null @@ -1,3 +0,0 @@ -# BSD on the PA already has ANSI include files which are c++ compatible. -USER_H = $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS) -STMP_FIXPROTO= diff --git a/gcc/config/pa/x-pa-hpux b/gcc/config/pa/x-pa-hpux deleted file mode 100755 index 1b8bb9f..0000000 --- a/gcc/config/pa/x-pa-hpux +++ /dev/null @@ -1,4 +0,0 @@ -ALLOCA=alloca.o - -# So putenv and other functions get seen by fixproto. -FIXPROTO_DEFINES = -D_HPUX_SOURCE diff --git a/gcc/config/pa/xm-pa.h b/gcc/config/pa/xm-pa.h deleted file mode 100755 index 0249055..0000000 --- a/gcc/config/pa/xm-pa.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Configuration for GNU C-compiler for PA-RISC. - Copyright (C) 1988, 1995 Free Software Foundation, Inc. - Contributed by Michael Tiemann (tiemann@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. */ - -extern int errno; - -/* #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 - -/* Doubles are stored in memory with the high order word first. This - matters when cross-compiling. */ -#define HOST_WORDS_BIG_ENDIAN 1 - -/* Place any machine-dependent include files here, in case we - are bootstrapping. */ - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ -#include "tm.h" - -/* Arguments to use with `exit'. */ -#define SUCCESS_EXIT_CODE 0 -#define FATAL_EXIT_CODE 33 - -/* Don't try to use sys_siglist. */ -#define NO_SYS_SIGLIST - -/* 4.3BSD, OSF1 and Lites on the PA are all derived from NET2 or - later code from Berkeley. */ -#define __BSD_NET2__ - -/* HP's compiler has problems with enum bitfields. */ -#define ONLY_INT_FIELDS - -/* Always claim to use C alloca; this prevents losing if building with - gcc -fno-builtin ... */ -#define USE_C_ALLOCA diff --git a/gcc/config/pa/xm-pahpux.h b/gcc/config/pa/xm-pahpux.h deleted file mode 100755 index 09c949b..0000000 --- a/gcc/config/pa/xm-pahpux.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Configuration for GNU C-compiler for PA-RISC. - Copyright (C) 1988, 1995, 1997 Free Software Foundation, Inc. - Contributed by Michael Tiemann (tiemann@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. */ - - -/* HP-UX is a flavor of System V */ -#define USG - -/* Use System V memory functions. */ -/* #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 - -/* Doubles are stored in memory with the high order word first. This - matters when cross-compiling. */ -#define HOST_WORDS_BIG_ENDIAN 1 - -/* Place any machine-dependent include files here, in case we - are bootstrapping. */ - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ -#include "tm.h" - -/* Arguments to use with `exit'. */ -#define SUCCESS_EXIT_CODE 0 -#define FATAL_EXIT_CODE 33 - -/* Don't try to use sys_siglist. */ -#define NO_SYS_SIGLIST - -/* HP's compiler has problems with enum bitfields. */ -#define ONLY_INT_FIELDS - -/* Always claim to use C alloca; this prevents losing if building with - gcc -fno-builtin ... " */ -#define USE_C_ALLOCA diff --git a/gcc/config/pa/xm-papro.h b/gcc/config/pa/xm-papro.h deleted file mode 100755 index d36e201..0000000 --- a/gcc/config/pa/xm-papro.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Configuration for GNU C-compiler for PA-RISC. - Copyright (C) 1994, 1995 Free Software Foundation, Inc. - Contributed by Michael Tiemann (tiemann@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. */ - -extern int errno; - -/* #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 - -/* Doubles are stored in memory with the high order word first. This - matters when cross-compiling. */ -#define HOST_WORDS_BIG_ENDIAN 1 - -/* Place any machine-dependent include files here, in case we - are bootstrapping. */ - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ -#include "tm.h" - -/* Arguments to use with `exit'. */ -#define SUCCESS_EXIT_CODE 0 -#define FATAL_EXIT_CODE 33 - -/* Don't try to use sys_siglist. */ -#define NO_SYS_SIGLIST - -/* HP's compiler has problems with enum bitfields. */ -#define ONLY_INT_FIELDS - -/* Always claim to use C alloca; this prevents losing if building with - gcc -fno-builtin ... */ -#define USE_C_ALLOCA |