From b6c9286a86e351a50cd49fc0cd8934d99875e14d Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Thu, 30 Nov 1995 20:02:16 +0000 Subject: [PATCH] update PowerPC support From-SVN: r10648 --- gcc/config/rs6000/aix3newas.h | 8 + gcc/config/rs6000/aix41.h | 8 + gcc/config/rs6000/eabi.asm | 644 ++++++++++++----------- gcc/config/rs6000/eabi.h | 53 +- gcc/config/rs6000/eabiaix.h | 21 +- gcc/config/rs6000/eabile.h | 21 +- gcc/config/rs6000/eabilesim.h | 43 +- gcc/config/rs6000/eabisim.h | 43 +- gcc/config/rs6000/mach.h | 1 + gcc/config/rs6000/netware.h | 5 +- gcc/config/rs6000/powerpc.h | 6 +- gcc/config/rs6000/rs6000.c | 934 +++++++++++++++++++++++++++------- gcc/config/rs6000/rs6000.h | 172 +++++-- gcc/config/rs6000/rs6000.md | 607 ++++++++++++++++------ gcc/config/rs6000/sysv4.h | 407 ++++++++++----- gcc/config/rs6000/sysv4le.h | 21 +- gcc/config/rs6000/t-ppc | 2 + gcc/config/rs6000/t-ppcgas | 15 +- 18 files changed, 2035 insertions(+), 976 deletions(-) diff --git a/gcc/config/rs6000/aix3newas.h b/gcc/config/rs6000/aix3newas.h index 31c0fd354d7..2d9b6530a34 100644 --- a/gcc/config/rs6000/aix3newas.h +++ b/gcc/config/rs6000/aix3newas.h @@ -45,6 +45,7 @@ Boston, MA 02111-1307, USA. */ %{mcpu=403: -mppc} \ %{mcpu=601: -m601} \ %{mcpu=603: -mppc} \ +%{mcpu=603e: -mppc} \ %{mcpu=604: -mppc}" /* Define the options for the binder: Start text at 512, align all segments @@ -65,10 +66,17 @@ Boston, MA 02111-1307, USA. */ as per README.RS6000. */ #undef LINK_SPEC +#ifndef CROSS_COMPILE #define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\ %{static:-bnso -bI:/lib/syscalls.exp} \ %{mcpu=common: milli.exp%s} \ %{!shared:%{g*:-bexport:/usr/lib/libg.exp}} %{shared:-bM:SRE}" +#else +#define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\ + %{static:-bnso} \ + %{mcpu=common: milli.exp%s} \ + %{shared:-bM:SRE}" +#endif /* These are not necessary when we pass -u to the assembler, and undefining them saves a great deal of space in object files. */ diff --git a/gcc/config/rs6000/aix41.h b/gcc/config/rs6000/aix41.h index caf1a8bc0b6..a35b3fa1f76 100644 --- a/gcc/config/rs6000/aix41.h +++ b/gcc/config/rs6000/aix41.h @@ -43,6 +43,7 @@ Boston, MA 02111-1307, USA. */ %{mcpu=403: -mppc} \ %{mcpu=601: -m601} \ %{mcpu=603: -mppc} \ +%{mcpu=603e: -mppc} \ %{mcpu=604: -mppc}" /* These are not necessary when we pass -u to the assembler, and undefining @@ -65,6 +66,13 @@ Boston, MA 02111-1307, USA. */ } #undef LINK_SPEC +#ifndef CROSS_COMPILE #define LINK_SPEC "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro} -bnodelcsect\ %{static:-bnso -bI:/lib/syscalls.exp} %{g*:-bexport:/usr/lib/libg.exp}\ %{shared:-bM:SRE}" +#else +#define LINK_SPEC "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro} -bnodelcsect\ + %{static:-bnso} \ + %{shared:-bM:SRE}" +#endif + diff --git a/gcc/config/rs6000/eabi.asm b/gcc/config/rs6000/eabi.asm index 38674dd7234..b5cf5c5f131 100644 --- a/gcc/config/rs6000/eabi.asm +++ b/gcc/config/rs6000/eabi.asm @@ -1,379 +1,367 @@ -# File to either setup register 2 to point to the GOT, or to adjust the -# pointers in the .got2 section to point to their new addresses. +/* Do any initializations needed for the eabi environment */ .file "eabi.asm" .section ".text" - .globl __eabi + #include "ppc-asm.h" .section ".got2","aw" -.LCTOC1 = . # +32768 +.LCTOC1 = . /* +32768 */ -# Table of addresses +/* Table of addresses */ .Ltable = .-.LCTOC1 - .long .LCTOC1 # address we are really at + .long .LCTOC1 /* address we are really at */ .Lgot = .-.LCTOC1 - .long _GLOBAL_OFFSET_TABLE_ # normal GOT address + .long _GLOBAL_OFFSET_TABLE_ /* normal GOT address */ .Lgots = .-.LCTOC1 - .long _GOT_START_ # start of .got section + .long _GOT_START_ /* start of .got section */ .Lgote = .-.LCTOC1 - .long _GOT_END_ # end of .got section + .long _GOT_END_ /* end of .got section */ .Lgot2s = .-.LCTOC1 - .long _GOT2_START_ # -mrelocatable GOT pointers start + .long _GOT2_START_ /* -mrelocatable GOT pointers start */ .Lgot2e = .-.LCTOC1 - .long _GOT2_END_ # -mrelocatable GOT pointers end + .long _GOT2_END_ /* -mrelocatable GOT pointers end */ .Lfixups = .-.LCTOC1 - .long _FIXUP_START_ # start of .fixup section + .long _FIXUP_START_ /* start of .fixup section */ .Lfixupe = .-.LCTOC1 - .long _FIXUP_END_ # end of .fixup section + .long _FIXUP_END_ /* end of .fixup section */ .text .Lptr: - .long .LCTOC1-.Laddr # PC relative pointer to .got2 - .long 0x4000 # traceback table + .long .LCTOC1-.Laddr /* PC relative pointer to .got2 */ -__eabi: mflr 0 - bl .Laddr # get current address +FUNC_START(__eabi) + mflr 0 + bl .Laddr /* get current address */ .Laddr: - mflr 12 # real address of .Laddr - lwz 11,(.Lptr-.Laddr)(12) # linker generated address of .LCTOC1 - add 11,11,12 # correct to real pointer - lwz 12,.Ltable(11) # get linker's idea of where .Laddr is - subf. 12,12,11 # calculate difference - mtlr 0 # restore link register - bc 4,2,.Lreloc # skip if we need to relocate - -# Only load up register 2 if there is a .got section - - lwz 3,.Lgots(11) # start of .got section - lwz 4,.Lgote(11) # end of .got section - cmpw 1,3,4 # .got section non-empty? + mflr 12 /* real address of .Laddr */ + lwz 11,(.Lptr-.Laddr)(12) /* linker generated address of .LCTOC1 */ + add 11,11,12 /* correct to real pointer */ + lwz 12,.Ltable(11) /* get linker's idea of where .Laddr is */ + subf. 12,12,11 /* calculate difference */ + mtlr 0 /* restore link register */ + bc 4,2,.Lreloc /* skip if we need to relocate */ + +/* Only load up register 2 if there is a .got section */ + + lwz 3,.Lgots(11) /* start of .got section */ + lwz 4,.Lgote(11) /* end of .got section */ + cmpw 1,3,4 /* .got section non-empty? */ bc 12,6,.Ldone -# Normal program, load up register 2 +/* Normal program, load up register 2 */ - lwz 2,.Lgot(11) # normal GOT address (obsolete in register 2) - mr 13,2 # also same as _SDA_BASE_ (V.4 small data ptr) - b __do_global_ctors # do any C++ global constructors (which returns to caller) + lwz 2,.Lgot(11) /* normal GOT address (obsolete in register 2) */ + mr 13,2 /* also same as _SDA_BASE_ (V.4 small data ptr) */ + b FUNC_NAME(__do_global_ctors) /* do any C++ global constructors (which returns to caller) */ -# We need to relocate the .got2 pointers. Don't load register 2 +/* We need to relocate the .got2 pointers. Don't load register 2 */ .Lreloc: - lwz 3,.Lgot2s(11) # GOT pointers start - lwz 4,.Lgot2e(11) # GOT pointers end - add 3,12,3 # adjust pointers + lwz 3,.Lgot2s(11) /* GOT pointers start */ + lwz 4,.Lgot2e(11) /* GOT pointers end */ + add 3,12,3 /* adjust pointers */ add 4,12,4 - cmpw 1,3,4 # any pointers to adjust + cmpw 1,3,4 /* any pointers to adjust */ bc 12,6,.Lfix .Lloop: - lwz 5,0(3) # next pointer - add 5,5,12 # adjust + lwz 5,0(3) /* next pointer */ + add 5,5,12 /* adjust */ stw 5,0(3) - addi 3,3,4 # bump to next word - cmpw 1,3,4 # more pointers to adjust? + addi 3,3,4 /* bump to next word */ + cmpw 1,3,4 /* more pointers to adjust? */ bc 4,6,.Lloop -# Fixup any user initialized pointers now (the compiler drops pointers to -# each of the relocs that it does in the .fixup section). Note, the pointers -# themselves have already been fixed up by the previous loop. +/* Fixup any user initialized pointers now (the compiler drops pointers to */ +/* each of the relocs that it does in the .fixup section). Note, the pointers */ +/* themselves have already been fixed up by the previous loop. */ .Lfix: - lwz 3,.Lfixups(11) # fixup pointers start - lwz 4,.Lfixupe(11) # fixup pointers end + lwz 3,.Lfixups(11) /* fixup pointers start */ + lwz 4,.Lfixupe(11) /* fixup pointers end */ - cmpw 1,3,4 # any user pointers to adjust + cmpw 1,3,4 /* any user pointers to adjust */ bc 12,6,.Ldone .Lfloop: - lwz 5,0(3) # next pointer - lwz 6,0(5) # get the pointer it points to - add 6,6,12 # adjust + lwz 5,0(3) /* next pointer */ + lwz 6,0(5) /* get the pointer it points to */ + add 6,6,12 /* adjust */ stw 6,0(5) - addi 3,3,4 # bump to next word - cmpw 1,3,4 # more pointers to adjust? + addi 3,3,4 /* bump to next word */ + cmpw 1,3,4 /* more pointers to adjust? */ bc 4,6,.Lfloop -# Done adjusting pointers, return +/* Done adjusting pointers, return */ .Ldone: - b __do_global_ctors # do any C++ global constructors (which returns to caller) - -# Routines for saving floating point registers, called by the compiler. -# Called with r11 pointing to the stack header word of the caller of the -# function, just beyond the end of the floating point save area. - - .globl _savefpr_14 - .globl _savefpr_15 - .globl _savefpr_16 - .globl _savefpr_17 - .globl _savefpr_18 - .globl _savefpr_19 - .globl _savefpr_20 - .globl _savefpr_21 - .globl _savefpr_22 - .globl _savefpr_23 - .globl _savefpr_24 - .globl _savefpr_25 - .globl _savefpr_26 - .globl _savefpr_27 - .globl _savefpr_28 - .globl _savefpr_29 - .globl _savefpr_30 - .globl _savefpr_31 - - .long 0x00400000 # traceback tag -_savefpr_14: stfd 14,-144(11) # save fp registers -_savefpr_15: stfd 15,-136(11) -_savefpr_16: stfd 16,-128(11) -_savefpr_17: stfd 17,-120(11) -_savefpr_18: stfd 18,-112(11) -_savefpr_19: stfd 19,-104(11) -_savefpr_20: stfd 20,-96(11) -_savefpr_21: stfd 21,-88(11) -_savefpr_22: stfd 22,-80(11) -_savefpr_23: stfd 23,-72(11) -_savefpr_24: stfd 24,-64(11) -_savefpr_25: stfd 25,-56(11) -_savefpr_26: stfd 26,-48(11) -_savefpr_27: stfd 27,-40(11) -_savefpr_28: stfd 28,-32(11) -_savefpr_29: stfd 29,-24(11) -_savefpr_30: stfd 30,-16(11) -_savefpr_31: stfd 31,-8(11) - blr - -# Routines for saving integer registers, called by the compiler. -# Called with r11 pointing to the stack header word of the caller of the -# function, just beyond the end of the integer save area. - - .globl _savegpr_14 - .globl _savegpr_15 - .globl _savegpr_16 - .globl _savegpr_17 - .globl _savegpr_18 - .globl _savegpr_19 - .globl _savegpr_20 - .globl _savegpr_21 - .globl _savegpr_22 - .globl _savegpr_23 - .globl _savegpr_24 - .globl _savegpr_25 - .globl _savegpr_26 - .globl _savegpr_27 - .globl _savegpr_28 - .globl _savegpr_29 - .globl _savegpr_30 - .globl _savegpr_31 - - .long 0x00400000 # traceback tag -_savegpr_14: stw 14,-72(11) # save gp registers -_savegpr_15: stw 15,-68(11) -_savegpr_16: stw 16,-64(11) -_savegpr_17: stw 17,-60(11) -_savegpr_18: stw 18,-56(11) -_savegpr_19: stw 19,-52(11) -_savegpr_20: stw 20,-48(11) -_savegpr_21: stw 21,-44(11) -_savegpr_22: stw 22,-40(11) -_savegpr_23: stw 23,-36(11) -_savegpr_24: stw 24,-32(11) -_savegpr_25: stw 25,-28(11) -_savegpr_26: stw 26,-24(11) -_savegpr_27: stw 27,-20(11) -_savegpr_28: stw 28,-16(11) -_savegpr_29: stw 29,-12(11) -_savegpr_30: stw 30,-8(11) -_savegpr_31: stw 31,-4(11) - blr - -# Routines for restoring floating point registers, called by the compiler. -# Called with r11 pointing to the stack header word of the caller of the -# function, just beyond the end of the floating point save area. - - .globl _restfpr_14 - .globl _restfpr_15 - .globl _restfpr_16 - .globl _restfpr_17 - .globl _restfpr_18 - .globl _restfpr_19 - .globl _restfpr_20 - .globl _restfpr_21 - .globl _restfpr_22 - .globl _restfpr_23 - .globl _restfpr_24 - .globl _restfpr_25 - .globl _restfpr_26 - .globl _restfpr_27 - .globl _restfpr_28 - .globl _restfpr_29 - .globl _restfpr_30 - .globl _restfpr_31 - - .long 0x00600000 # traceback tag -_restfpr_14: lfd 14,-144(11) # restore fp registers -_restfpr_15: lfd 15,-136(11) -_restfpr_16: lfd 16,-128(11) -_restfpr_17: lfd 17,-120(11) -_restfpr_18: lfd 18,-112(11) -_restfpr_19: lfd 19,-104(11) -_restfpr_20: lfd 20,-96(11) -_restfpr_21: lfd 21,-88(11) -_restfpr_22: lfd 22,-80(11) -_restfpr_23: lfd 23,-72(11) -_restfpr_24: lfd 24,-64(11) -_restfpr_25: lfd 25,-56(11) -_restfpr_26: lfd 26,-48(11) -_restfpr_27: lfd 27,-40(11) -_restfpr_28: lfd 28,-32(11) -_restfpr_29: lfd 29,-24(11) -_restfpr_30: lfd 30,-16(11) -_restfpr_31: lfd 31,-8(11) - blr - -# Routines for restoring integer registers, called by the compiler. -# Called with r11 pointing to the stack header word of the caller of the -# function, just beyond the end of the integer restore area. - - .globl _restgpr_14 - .globl _restgpr_15 - .globl _restgpr_16 - .globl _restgpr_17 - .globl _restgpr_18 - .globl _restgpr_19 - .globl _restgpr_20 - .globl _restgpr_21 - .globl _restgpr_22 - .globl _restgpr_23 - .globl _restgpr_24 - .globl _restgpr_25 - .globl _restgpr_26 - .globl _restgpr_27 - .globl _restgpr_28 - .globl _restgpr_29 - .globl _restgpr_30 - .globl _restgpr_31 - - .long 0x00600000 # traceback tag -_restgpr_14: lwz 14,-72(11) # rest gp registers -_restgpr_15: lwz 15,-68(11) -_restgpr_16: lwz 16,-64(11) -_restgpr_17: lwz 17,-60(11) -_restgpr_18: lwz 18,-56(11) -_restgpr_19: lwz 19,-52(11) -_restgpr_20: lwz 20,-48(11) -_restgpr_21: lwz 21,-44(11) -_restgpr_22: lwz 22,-40(11) -_restgpr_23: lwz 23,-36(11) -_restgpr_24: lwz 24,-32(11) -_restgpr_25: lwz 25,-28(11) -_restgpr_26: lwz 26,-24(11) -_restgpr_27: lwz 27,-20(11) -_restgpr_28: lwz 28,-16(11) -_restgpr_29: lwz 29,-12(11) -_restgpr_30: lwz 30,-8(11) -_restgpr_31: lwz 31,-4(11) - blr - -# Routines for restoring floating point registers, called by the compiler. -# Called with r11 pointing to the stack header word of the caller of the -# function, just beyond the end of the floating point save area. -# In addition to restoring the fp registers, it will return to the caller's -# caller - - .globl _restfpr_14_x - .globl _restfpr_15_x - .globl _restfpr_16_x - .globl _restfpr_17_x - .globl _restfpr_18_x - .globl _restfpr_19_x - .globl _restfpr_20_x - .globl _restfpr_21_x - .globl _restfpr_22_x - .globl _restfpr_23_x - .globl _restfpr_24_x - .globl _restfpr_25_x - .globl _restfpr_26_x - .globl _restfpr_27_x - .globl _restfpr_28_x - .globl _restfpr_29_x - .globl _restfpr_30_x - .globl _restfpr_31_x - - .long 0x00600000 # traceback tag -_restfpr_14_x: lfd 14,-144(11) # restore fp registers -_restfpr_15_x: lfd 15,-136(11) -_restfpr_16_x: lfd 16,-128(11) -_restfpr_17_x: lfd 17,-120(11) -_restfpr_18_x: lfd 18,-112(11) -_restfpr_19_x: lfd 19,-104(11) -_restfpr_20_x: lfd 20,-96(11) -_restfpr_21_x: lfd 21,-88(11) -_restfpr_22_x: lfd 22,-80(11) -_restfpr_23_x: lfd 23,-72(11) -_restfpr_24_x: lfd 24,-64(11) -_restfpr_25_x: lfd 25,-56(11) -_restfpr_26_x: lfd 26,-48(11) -_restfpr_27_x: lfd 27,-40(11) -_restfpr_28_x: lfd 28,-32(11) -_restfpr_29_x: lfd 29,-24(11) -_restfpr_30_x: lfd 30,-16(11) -_restfpr_31_x: lwz 0,4(11) - lfd 31,-8(11) - mtlr 0 - mr 1,11 - blr - -# Routines for restoring integer registers, called by the compiler. -# Called with r11 pointing to the stack header word of the caller of the -# function, just beyond the end of the integer restore area. - - .globl _restgpr_14_x - .globl _restgpr_15_x - .globl _restgpr_16_x - .globl _restgpr_17_x - .globl _restgpr_18_x - .globl _restgpr_19_x - .globl _restgpr_20_x - .globl _restgpr_21_x - .globl _restgpr_22_x - .globl _restgpr_23_x - .globl _restgpr_24_x - .globl _restgpr_25_x - .globl _restgpr_26_x - .globl _restgpr_27_x - .globl _restgpr_28_x - .globl _restgpr_29_x - .globl _restgpr_30_x - .globl _restgpr_31_x - - .long 0x00600000 # traceback tag -_restgpr_14_x: lwz 14,-72(11) # rest gp registers -_restgpr_15_x: lwz 15,-68(11) -_restgpr_16_x: lwz 16,-64(11) -_restgpr_17_x: lwz 17,-60(11) -_restgpr_18_x: lwz 18,-56(11) -_restgpr_19_x: lwz 19,-52(11) -_restgpr_20_x: lwz 20,-48(11) -_restgpr_21_x: lwz 21,-44(11) -_restgpr_22_x: lwz 22,-40(11) -_restgpr_23_x: lwz 23,-36(11) -_restgpr_24_x: lwz 24,-32(11) -_restgpr_25_x: lwz 25,-28(11) -_restgpr_26_x: lwz 26,-24(11) -_restgpr_27_x: lwz 27,-20(11) -_restgpr_28_x: lwz 28,-16(11) -_restgpr_29_x: lwz 29,-12(11) -_restgpr_30_x: lwz 30,-8(11) -_restgpr_31_x: lwz 0,4(11) - lwz 31,-4(11) - mtlr 0 - mr 1,11 - blr + b FUNC_NAME(__do_global_ctors) /* do any C++ global constructors (which returns to caller) */ +FUNC_END(__eabi) + +/* Routines for saving floating point registers, called by the compiler. */ +/* Called with r11 pointing to the stack header word of the caller of the */ +/* function, just beyond the end of the floating point save area. */ + +FUNC_START(_savefpr_14) stfd 14,-144(11) /* save fp registers */ +FUNC_START(_savefpr_15) stfd 15,-136(11) +FUNC_START(_savefpr_16) stfd 16,-128(11) +FUNC_START(_savefpr_17) stfd 17,-120(11) +FUNC_START(_savefpr_18) stfd 18,-112(11) +FUNC_START(_savefpr_19) stfd 19,-104(11) +FUNC_START(_savefpr_20) stfd 20,-96(11) +FUNC_START(_savefpr_21) stfd 21,-88(11) +FUNC_START(_savefpr_22) stfd 22,-80(11) +FUNC_START(_savefpr_23) stfd 23,-72(11) +FUNC_START(_savefpr_24) stfd 24,-64(11) +FUNC_START(_savefpr_25) stfd 25,-56(11) +FUNC_START(_savefpr_26) stfd 26,-48(11) +FUNC_START(_savefpr_27) stfd 27,-40(11) +FUNC_START(_savefpr_28) stfd 28,-32(11) +FUNC_START(_savefpr_29) stfd 29,-24(11) +FUNC_START(_savefpr_30) stfd 30,-16(11) +FUNC_START(_savefpr_31) stfd 31,-8(11) + blr +FUNC_END(_savefpr_31) +FUNC_END(_savefpr_30) +FUNC_END(_savefpr_29) +FUNC_END(_savefpr_28) +FUNC_END(_savefpr_27) +FUNC_END(_savefpr_26) +FUNC_END(_savefpr_25) +FUNC_END(_savefpr_24) +FUNC_END(_savefpr_23) +FUNC_END(_savefpr_22) +FUNC_END(_savefpr_21) +FUNC_END(_savefpr_20) +FUNC_END(_savefpr_19) +FUNC_END(_savefpr_18) +FUNC_END(_savefpr_17) +FUNC_END(_savefpr_16) +FUNC_END(_savefpr_15) +FUNC_END(_savefpr_14) + +/* Routines for saving integer registers, called by the compiler. */ +/* Called with r11 pointing to the stack header word of the caller of the */ +/* function, just beyond the end of the integer save area. */ + +FUNC_START(_savegpr_14) stw 14,-72(11) /* save gp registers */ +FUNC_START(_savegpr_15) stw 15,-68(11) +FUNC_START(_savegpr_16) stw 16,-64(11) +FUNC_START(_savegpr_17) stw 17,-60(11) +FUNC_START(_savegpr_18) stw 18,-56(11) +FUNC_START(_savegpr_19) stw 19,-52(11) +FUNC_START(_savegpr_20) stw 20,-48(11) +FUNC_START(_savegpr_21) stw 21,-44(11) +FUNC_START(_savegpr_22) stw 22,-40(11) +FUNC_START(_savegpr_23) stw 23,-36(11) +FUNC_START(_savegpr_24) stw 24,-32(11) +FUNC_START(_savegpr_25) stw 25,-28(11) +FUNC_START(_savegpr_26) stw 26,-24(11) +FUNC_START(_savegpr_27) stw 27,-20(11) +FUNC_START(_savegpr_28) stw 28,-16(11) +FUNC_START(_savegpr_29) stw 29,-12(11) +FUNC_START(_savegpr_30) stw 30,-8(11) +FUNC_START(_savegpr_31) stw 31,-4(11) + blr +FUNC_END(_savegpr_31) +FUNC_END(_savegpr_30) +FUNC_END(_savegpr_29) +FUNC_END(_savegpr_28) +FUNC_END(_savegpr_27) +FUNC_END(_savegpr_26) +FUNC_END(_savegpr_25) +FUNC_END(_savegpr_24) +FUNC_END(_savegpr_23) +FUNC_END(_savegpr_22) +FUNC_END(_savegpr_21) +FUNC_END(_savegpr_20) +FUNC_END(_savegpr_19) +FUNC_END(_savegpr_18) +FUNC_END(_savegpr_17) +FUNC_END(_savegpr_16) +FUNC_END(_savegpr_15) +FUNC_END(_savegpr_14) + +/* Routines for restoring floating point registers, called by the compiler. */ +/* Called with r11 pointing to the stack header word of the caller of the */ +/* function, just beyond the end of the floating point save area. */ + +FUNC_START(_restfpr_14) lfd 14,-144(11) /* restore fp registers */ +FUNC_START(_restfpr_15) lfd 15,-136(11) +FUNC_START(_restfpr_16) lfd 16,-128(11) +FUNC_START(_restfpr_17) lfd 17,-120(11) +FUNC_START(_restfpr_18) lfd 18,-112(11) +FUNC_START(_restfpr_19) lfd 19,-104(11) +FUNC_START(_restfpr_20) lfd 20,-96(11) +FUNC_START(_restfpr_21) lfd 21,-88(11) +FUNC_START(_restfpr_22) lfd 22,-80(11) +FUNC_START(_restfpr_23) lfd 23,-72(11) +FUNC_START(_restfpr_24) lfd 24,-64(11) +FUNC_START(_restfpr_25) lfd 25,-56(11) +FUNC_START(_restfpr_26) lfd 26,-48(11) +FUNC_START(_restfpr_27) lfd 27,-40(11) +FUNC_START(_restfpr_28) lfd 28,-32(11) +FUNC_START(_restfpr_29) lfd 29,-24(11) +FUNC_START(_restfpr_30) lfd 30,-16(11) +FUNC_START(_restfpr_31) lfd 31,-8(11) + blr +FUNC_END(_restfpr_31) +FUNC_END(_restfpr_30) +FUNC_END(_restfpr_29) +FUNC_END(_restfpr_28) +FUNC_END(_restfpr_27) +FUNC_END(_restfpr_26) +FUNC_END(_restfpr_25) +FUNC_END(_restfpr_24) +FUNC_END(_restfpr_23) +FUNC_END(_restfpr_22) +FUNC_END(_restfpr_21) +FUNC_END(_restfpr_20) +FUNC_END(_restfpr_19) +FUNC_END(_restfpr_18) +FUNC_END(_restfpr_17) +FUNC_END(_restfpr_16) +FUNC_END(_restfpr_15) +FUNC_END(_restfpr_14) + +/* Routines for restoring integer registers, called by the compiler. */ +/* Called with r11 pointing to the stack header word of the caller of the */ +/* function, just beyond the end of the integer restore area. */ + +FUNC_START(_restgpr_14) lwz 14,-72(11) /* restore gp registers */ +FUNC_START(_restgpr_15) lwz 15,-68(11) +FUNC_START(_restgpr_16) lwz 16,-64(11) +FUNC_START(_restgpr_17) lwz 17,-60(11) +FUNC_START(_restgpr_18) lwz 18,-56(11) +FUNC_START(_restgpr_19) lwz 19,-52(11) +FUNC_START(_restgpr_20) lwz 20,-48(11) +FUNC_START(_restgpr_21) lwz 21,-44(11) +FUNC_START(_restgpr_22) lwz 22,-40(11) +FUNC_START(_restgpr_23) lwz 23,-36(11) +FUNC_START(_restgpr_24) lwz 24,-32(11) +FUNC_START(_restgpr_25) lwz 25,-28(11) +FUNC_START(_restgpr_26) lwz 26,-24(11) +FUNC_START(_restgpr_27) lwz 27,-20(11) +FUNC_START(_restgpr_28) lwz 28,-16(11) +FUNC_START(_restgpr_29) lwz 29,-12(11) +FUNC_START(_restgpr_30) lwz 30,-8(11) +FUNC_START(_restgpr_31) lwz 31,-4(11) + blr +FUNC_END(_restgpr_31) +FUNC_END(_restgpr_30) +FUNC_END(_restgpr_29) +FUNC_END(_restgpr_28) +FUNC_END(_restgpr_27) +FUNC_END(_restgpr_26) +FUNC_END(_restgpr_25) +FUNC_END(_restgpr_24) +FUNC_END(_restgpr_23) +FUNC_END(_restgpr_22) +FUNC_END(_restgpr_21) +FUNC_END(_restgpr_20) +FUNC_END(_restgpr_19) +FUNC_END(_restgpr_18) +FUNC_END(_restgpr_17) +FUNC_END(_restgpr_16) +FUNC_END(_restgpr_15) +FUNC_END(_restgpr_14) + +/* Routines for restoring floating point registers, called by the compiler. */ +/* Called with r11 pointing to the stack header word of the caller of the */ +/* function, just beyond the end of the floating point save area. */ +/* In addition to restoring the fp registers, it will return to the caller's */ +/* caller */ + +FUNC_START(_restfpr_14_x) lfd 14,-144(11) /* restore fp registers */ +FUNC_START(_restfpr_15_x) lfd 15,-136(11) +FUNC_START(_restfpr_16_x) lfd 16,-128(11) +FUNC_START(_restfpr_17_x) lfd 17,-120(11) +FUNC_START(_restfpr_18_x) lfd 18,-112(11) +FUNC_START(_restfpr_19_x) lfd 19,-104(11) +FUNC_START(_restfpr_20_x) lfd 20,-96(11) +FUNC_START(_restfpr_21_x) lfd 21,-88(11) +FUNC_START(_restfpr_22_x) lfd 22,-80(11) +FUNC_START(_restfpr_23_x) lfd 23,-72(11) +FUNC_START(_restfpr_24_x) lfd 24,-64(11) +FUNC_START(_restfpr_25_x) lfd 25,-56(11) +FUNC_START(_restfpr_26_x) lfd 26,-48(11) +FUNC_START(_restfpr_27_x) lfd 27,-40(11) +FUNC_START(_restfpr_28_x) lfd 28,-32(11) +FUNC_START(_restfpr_29_x) lfd 29,-24(11) +FUNC_START(_restfpr_30_x) lfd 30,-16(11) +FUNC_START(_restfpr_31_x) lwz 0,4(11) + lfd 31,-8(11) + mtlr 0 + mr 1,11 + blr +FUNC_END(_restfpr_31_x) +FUNC_END(_restfpr_30_x) +FUNC_END(_restfpr_29_x) +FUNC_END(_restfpr_28_x) +FUNC_END(_restfpr_27_x) +FUNC_END(_restfpr_26_x) +FUNC_END(_restfpr_25_x) +FUNC_END(_restfpr_24_x) +FUNC_END(_restfpr_23_x) +FUNC_END(_restfpr_22_x) +FUNC_END(_restfpr_21_x) +FUNC_END(_restfpr_20_x) +FUNC_END(_restfpr_19_x) +FUNC_END(_restfpr_18_x) +FUNC_END(_restfpr_17_x) +FUNC_END(_restfpr_16_x) +FUNC_END(_restfpr_15_x) +FUNC_END(_restfpr_14_x) + +/* Routines for restoring integer registers, called by the compiler. */ +/* Called with r11 pointing to the stack header word of the caller of the */ +/* function, just beyond the end of the integer restore area. */ + +FUNC_START(_restgpr_14_x) lwz 14,-72(11) /* restore gp registers */ +FUNC_START(_restgpr_15_x) lwz 15,-68(11) +FUNC_START(_restgpr_16_x) lwz 16,-64(11) +FUNC_START(_restgpr_17_x) lwz 17,-60(11) +FUNC_START(_restgpr_18_x) lwz 18,-56(11) +FUNC_START(_restgpr_19_x) lwz 19,-52(11) +FUNC_START(_restgpr_20_x) lwz 20,-48(11) +FUNC_START(_restgpr_21_x) lwz 21,-44(11) +FUNC_START(_restgpr_22_x) lwz 22,-40(11) +FUNC_START(_restgpr_23_x) lwz 23,-36(11) +FUNC_START(_restgpr_24_x) lwz 24,-32(11) +FUNC_START(_restgpr_25_x) lwz 25,-28(11) +FUNC_START(_restgpr_26_x) lwz 26,-24(11) +FUNC_START(_restgpr_27_x) lwz 27,-20(11) +FUNC_START(_restgpr_28_x) lwz 28,-16(11) +FUNC_START(_restgpr_29_x) lwz 29,-12(11) +FUNC_START(_restgpr_30_x) lwz 30,-8(11) +FUNC_START(_restgpr_31_x) lwz 0,4(11) + lwz 31,-4(11) + mtlr 0 + mr 1,11 + blr +FUNC_END(_restgpr_31_x) +FUNC_END(_restgpr_30_x) +FUNC_END(_restgpr_29_x) +FUNC_END(_restgpr_28_x) +FUNC_END(_restgpr_27_x) +FUNC_END(_restgpr_26_x) +FUNC_END(_restgpr_25_x) +FUNC_END(_restgpr_24_x) +FUNC_END(_restgpr_23_x) +FUNC_END(_restgpr_22_x) +FUNC_END(_restgpr_21_x) +FUNC_END(_restgpr_20_x) +FUNC_END(_restgpr_19_x) +FUNC_END(_restgpr_18_x) +FUNC_END(_restgpr_17_x) +FUNC_END(_restgpr_16_x) +FUNC_END(_restgpr_15_x) +FUNC_END(_restgpr_14_x) diff --git a/gcc/config/rs6000/eabi.h b/gcc/config/rs6000/eabi.h index 0f8bdb5ead4..6044be7622e 100644 --- a/gcc/config/rs6000/eabi.h +++ b/gcc/config/rs6000/eabi.h @@ -60,7 +60,6 @@ Boston, MA 02111-1307, USA. */ /* Invoke an initializer function to set up the GOT */ #define NAME__MAIN "__eabi" -#define INVOKE__main 1 #undef TARGET_VERSION #define TARGET_VERSION fprintf (stderr, " (PowerPC Embedded)"); @@ -69,57 +68,19 @@ Boston, MA 02111-1307, USA. */ #define CPP_PREDEFINES \ "-DPPC -D__embedded__ -Asystem(embedded) -Acpu(powerpc) -Amachine(powerpc)" -/* Don't use startfiles or libraries except for libgcc.a */ +/* Use the simulator crt0 or mvme and libgloss/newlib libraries if desired */ #undef STARTFILE_SPEC -#define STARTFILE_SPEC "" +#define STARTFILE_SPEC "\ +%{mmvme: mvme-crt0.o%s} \ +%{msim: sim-crt0.o%s}" #undef LIB_SPEC -#define LIB_SPEC "" +#define LIB_SPEC "\ +%{mmvme: -lmvme -lc -lmvme} \ +%{msim: -lsim -lc -lsim}" #undef LIBGCC_SPEC #define LIBGCC_SPEC "libgcc.a%s" #undef ENDFILE_SPEC #define ENDFILE_SPEC "" - -/* This is how to output an assembler line defining an `int' constant. - For -mrelocatable, we mark all addresses that need to be fixed up - in the .fixup section. */ -#undef ASM_OUTPUT_INT -#define ASM_OUTPUT_INT(FILE,VALUE) \ -do { \ - static int recurse = 0; \ - if (TARGET_RELOCATABLE \ - && in_section != in_toc \ - && in_section != in_text \ - && in_section != in_ctors \ - && in_section != in_dtors \ - && !recurse \ - && GET_CODE (VALUE) != CONST_INT \ - && GET_CODE (VALUE) != CONST_DOUBLE \ - && CONSTANT_P (VALUE)) \ - { \ - static int labelno = 0; \ - char buf[256], *p; \ - \ - recurse = 1; \ - ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", labelno++); \ - STRIP_NAME_ENCODING (p, buf); \ - fprintf (FILE, "%s:\n", p); \ - fprintf (FILE, "\t.long ("); \ - output_addr_const (FILE, (VALUE)); \ - fprintf (FILE, ")@fixup\n"); \ - fprintf (FILE, "\t.section\t\".fixup\",\"aw\"\n"); \ - ASM_OUTPUT_ALIGN (FILE, 2); \ - fprintf (FILE, "\t.long\t%s\n", p); \ - fprintf (FILE, "\t.previous\n"); \ - recurse = 0; \ - } \ - else \ - { \ - fprintf (FILE, "\t.long "); \ - output_addr_const (FILE, (VALUE)); \ - fprintf (FILE, "\n"); \ - } \ -} while (0) - diff --git a/gcc/config/rs6000/eabiaix.h b/gcc/config/rs6000/eabiaix.h index 6e92d17df8c..c07f6d63bca 100644 --- a/gcc/config/rs6000/eabiaix.h +++ b/gcc/config/rs6000/eabiaix.h @@ -28,7 +28,9 @@ Boston, MA 02111-1307, USA. */ #define CPP_SPEC "\ %{posix: -D_POSIX_SOURCE} \ %{mrelocatable: -D_RELOCATABLE} \ -%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_AIX}} \ +%{mcall-sysv: -D_CALL_SYSV} %{mcall-nt: -D_CALL_NT} \ +%{mcall-aix: -D_CALL_AIX} %{mcall-aixdesc: -D_CALL_AIX -D_CALL_AIXDESC} \ +%{!mcall-sysv: %{!mcall-aix: %{!mcall-aixdesc: %{!mcall-nt: -D_CALL_AIX}}}} \ %{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \ %{mlittle: -D_LITTLE_ENDIAN -Amachine(littleendian)} \ %{mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)} \ @@ -49,5 +51,20 @@ Boston, MA 02111-1307, USA. */ %{mcpu=rsc1: -D_ARCH_PWR} \ %{mcpu=403: -D_ARCH_PPC} \ %{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \ +%{mcpu=602: -D_ARCH_PPC} \ %{mcpu=603: -D_ARCH_PPC} \ -%{mcpu=604: -D_ARCH_PPC}" +%{mcpu=603e: -D_ARCH_PPC} \ +%{mcpu=604: -D_ARCH_PPC} \ +%{mcpu=620: -D_ARCH_PPC}" + +/* Define this macro as a C expression for the initializer of an + array of string to tell the driver program which options are + defaults for this target and thus do not need to be handled + specially when using `MULTILIB_OPTIONS'. + + Do not define this macro if `MULTILIB_OPTIONS' is not defined in + the target makefile fragment or if none of the options listed in + `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */ + +#undef MULTILIB_DEFAULTS +#define MULTILIB_DEFAULTS { "mbig", "mbig-endian", "mcall-aix" } diff --git a/gcc/config/rs6000/eabile.h b/gcc/config/rs6000/eabile.h index 11ff65ea9fa..430660b1d6d 100644 --- a/gcc/config/rs6000/eabile.h +++ b/gcc/config/rs6000/eabile.h @@ -29,7 +29,9 @@ Boston, MA 02111-1307, USA. */ #define CPP_SPEC "\ %{posix: -D_POSIX_SOURCE} \ %{mrelocatable: -D_RELOCATABLE} \ -%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \ +%{mcall-sysv: -D_CALL_SYSV} %{mcall-nt: -D_CALL_NT} \ +%{mcall-aix: -D_CALL_AIX} %{mcall-aixdesc: -D_CALL_AIX -D_CALL_AIXDESC} \ +%{!mcall-sysv: %{!mcall-aix: %{!mcall-aixdesc: %{!mcall-nt: -D_CALL_SYSV}}}} \ %{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \ %{mbig: -D_BIG_ENDIAN -Amachine(bigendian)} \ %{mbig-endian: -D_BIG_ENDIAN -Amachine(bigendian)} \ @@ -50,5 +52,20 @@ Boston, MA 02111-1307, USA. */ %{mcpu=rsc1: -D_ARCH_PWR} \ %{mcpu=403: -D_ARCH_PPC} \ %{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \ +%{mcpu=602: -D_ARCH_PPC} \ %{mcpu=603: -D_ARCH_PPC} \ -%{mcpu=604: -D_ARCH_PPC}" +%{mcpu=603e: -D_ARCH_PPC} \ +%{mcpu=604: -D_ARCH_PPC} \ +%{mcpu=620: -D_ARCH_PPC}" + +/* Define this macro as a C expression for the initializer of an + array of string to tell the driver program which options are + defaults for this target and thus do not need to be handled + specially when using `MULTILIB_OPTIONS'. + + Do not define this macro if `MULTILIB_OPTIONS' is not defined in + the target makefile fragment or if none of the options listed in + `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */ + +#undef MULTILIB_DEFAULTS +#define MULTILIB_DEFAULTS { "mlittle", "mlittle-endian", "mcall-sysv" } diff --git a/gcc/config/rs6000/eabilesim.h b/gcc/config/rs6000/eabilesim.h index afc85652676..4df32f77742 100644 --- a/gcc/config/rs6000/eabilesim.h +++ b/gcc/config/rs6000/eabilesim.h @@ -22,11 +22,6 @@ Boston, MA 02111-1307, USA. */ #include "rs6000/eabile.h" -/* Right now, the simulator doesn't handle floating point, so disable it - by default. */ -#undef TARGET_DEFAULT -#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_LITTLE_ENDIAN | MASK_SOFT_FLOAT) - #undef TARGET_VERSION #define TARGET_VERSION fprintf (stderr, " (PowerPC Simulated)"); @@ -34,40 +29,16 @@ Boston, MA 02111-1307, USA. */ #define CPP_PREDEFINES \ "-DPPC -D__embedded__ -D__simulator__ -Asystem(embedded) -Asystem(simulator) -Acpu(powerpc) -Amachine(powerpc)" -#undef CPP_SPEC -#define CPP_SPEC "\ -%{posix: -D_POSIX_SOURCE} \ -%{mrelocatable: -D_RELOCATABLE} \ -%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \ -%{!mhard-float: -D_SOFT_FLOAT} \ -%{mlittle: -D_LITTLE_ENDIAN -Amachine(littleendian)} \ -%{mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)} \ -%{!mlittle: %{!mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)}} \ -%{!mcpu*: \ - %{mpower: %{!mpower2: -D_ARCH_PWR}} \ - %{mpower2: -D_ARCH_PWR2} \ - %{mpowerpc*: -D_ARCH_PPC} \ - %{mno-powerpc: %{!mpower: %{!mpower2: -D_ARCH_COM}}} \ - %{!mno-powerpc: -D_ARCH_PPC}} \ -%{mcpu=common: -D_ARCH_COM} \ -%{mcpu=power: -D_ARCH_PWR} \ -%{mcpu=powerpc: -D_ARCH_PPC} \ -%{mcpu=rios: -D_ARCH_PWR} \ -%{mcpu=rios1: -D_ARCH_PWR} \ -%{mcpu=rios2: -D_ARCH_PWR2} \ -%{mcpu=rsc: -D_ARCH_PWR} \ -%{mcpu=rsc1: -D_ARCH_PWR} \ -%{mcpu=403: -D_ARCH_PPC} \ -%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \ -%{mcpu=603: -D_ARCH_PPC} \ -%{mcpu=604: -D_ARCH_PPC}" - -/* Use the simulator crt0 and libgloss/newlib libraries */ +/* Use the simulator crt0 or mvme and libgloss/newlib libraries if desired */ #undef STARTFILE_SPEC -#define STARTFILE_SPEC "sim-crt0.o%s" +#define STARTFILE_SPEC "\ +%{mmvme: mvme-crt0.o%s} \ +%{!mmvme: sim-crt0.o%s}" #undef LIB_SPEC -#define LIB_SPEC "-lsim -lc -lsim" +#define LIB_SPEC "\ +%{mmvme: -lmvme -lc -lmvme} \ +%{!mmvme: -lsim -lc -lsim}" #undef LIBGCC_SPEC #define LIBGCC_SPEC "libgcc.a%s" diff --git a/gcc/config/rs6000/eabisim.h b/gcc/config/rs6000/eabisim.h index 98c9f0ea8bb..826801c8b96 100644 --- a/gcc/config/rs6000/eabisim.h +++ b/gcc/config/rs6000/eabisim.h @@ -22,11 +22,6 @@ Boston, MA 02111-1307, USA. */ #include "rs6000/eabi.h" -/* Right now, the simulator doesn't handle floating point, so disable it - by default. */ -#undef TARGET_DEFAULT -#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_SOFT_FLOAT) - #undef TARGET_VERSION #define TARGET_VERSION fprintf (stderr, " (PowerPC Simulated)"); @@ -34,40 +29,16 @@ Boston, MA 02111-1307, USA. */ #define CPP_PREDEFINES \ "-DPPC -D__embedded__ -D__simulator__ -Asystem(embedded) -Asystem(simulator) -Acpu(powerpc) -Amachine(powerpc)" -#undef CPP_SPEC -#define CPP_SPEC "\ -%{posix: -D_POSIX_SOURCE} \ -%{mrelocatable: -D_RELOCATABLE} \ -%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \ -%{!mhard-float: -D_SOFT_FLOAT} \ -%{mlittle: -D_LITTLE_ENDIAN -Amachine(littleendian)} \ -%{mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)} \ -%{!mlittle: %{!mlittle-endian: -D_BIG_ENDIAN -Amachine(bigendian)}} \ -%{!mcpu*: \ - %{mpower: %{!mpower2: -D_ARCH_PWR}} \ - %{mpower2: -D_ARCH_PWR2} \ - %{mpowerpc*: -D_ARCH_PPC} \ - %{mno-powerpc: %{!mpower: %{!mpower2: -D_ARCH_COM}}} \ - %{!mno-powerpc: -D_ARCH_PPC}} \ -%{mcpu=common: -D_ARCH_COM} \ -%{mcpu=power: -D_ARCH_PWR} \ -%{mcpu=powerpc: -D_ARCH_PPC} \ -%{mcpu=rios: -D_ARCH_PWR} \ -%{mcpu=rios1: -D_ARCH_PWR} \ -%{mcpu=rios2: -D_ARCH_PWR2} \ -%{mcpu=rsc: -D_ARCH_PWR} \ -%{mcpu=rsc1: -D_ARCH_PWR} \ -%{mcpu=403: -D_ARCH_PPC} \ -%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \ -%{mcpu=603: -D_ARCH_PPC} \ -%{mcpu=604: -D_ARCH_PPC}" - -/* Use the simulator crt0 and libgloss/newlib libraries */ +/* Use the simulator crt0 or mvme and libgloss/newlib libraries if desired */ #undef STARTFILE_SPEC -#define STARTFILE_SPEC "sim-crt0.o%s" +#define STARTFILE_SPEC "\ +%{mmvme: mvme-crt0.o%s} \ +%{!mmvme: sim-crt0.o%s}" #undef LIB_SPEC -#define LIB_SPEC "-lsim -lc -lsim" +#define LIB_SPEC "\ +%{mmvme: -lmvme -lc -lmvme} \ +%{!mmvme: -lsim -lc -lsim}" #undef LIBGCC_SPEC #define LIBGCC_SPEC "libgcc.a%s" diff --git a/gcc/config/rs6000/mach.h b/gcc/config/rs6000/mach.h index c812c6bb46f..bb4e8b4df84 100644 --- a/gcc/config/rs6000/mach.h +++ b/gcc/config/rs6000/mach.h @@ -20,6 +20,7 @@ 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_AIX 0 #include "rs6000/rs6000.h" diff --git a/gcc/config/rs6000/netware.h b/gcc/config/rs6000/netware.h index 8e86a3438dd..7d5bbaa2b37 100644 --- a/gcc/config/rs6000/netware.h +++ b/gcc/config/rs6000/netware.h @@ -19,6 +19,8 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define TARGET_AIX 0 + #include "rs6000/powerpc.h" /* Don't generate XCOFF debugging information. */ @@ -32,8 +34,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* The XCOFF support uses weird symbol suffixes, which we don't want for ELF. */ -#undef RS6000_OUTPUT_BASENAME -#define RS6000_OUTPUT_BASENAME(FILE, NAME) assemble_name (FILE, NAME) +#undef STRIP_NAME_ENCODING /* Don't bother to output .extern pseudo-ops. They are not needed by ELF assemblers. */ diff --git a/gcc/config/rs6000/powerpc.h b/gcc/config/rs6000/powerpc.h index e8f6a17168a..96e15d7c0fc 100644 --- a/gcc/config/rs6000/powerpc.h +++ b/gcc/config/rs6000/powerpc.h @@ -43,6 +43,7 @@ Boston, MA 02111-1307, USA. */ %{mcpu=403: -mppc} \ %{mcpu=601: -m601} \ %{mcpu=603: -mppc} \ +%{mcpu=603e: -mppc} \ %{mcpu=604: -mppc}" #undef CPP_PREDEFINES @@ -68,8 +69,11 @@ Boston, MA 02111-1307, USA. */ %{mcpu=rsc1: -D_ARCH_PWR} \ %{mcpu=403: -D_ARCH_PPC} \ %{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \ +%{mcpu=602: -D_ARCH_PPC} \ %{mcpu=603: -D_ARCH_PPC} \ -%{mcpu=604: -D_ARCH_PPC}" +%{mcpu=603e: -D_ARCH_PPC} \ +%{mcpu=604: -D_ARCH_PPC} \ +%{mcpu=620: -D_ARCH_PPC}" #undef TARGET_DEFAULT #define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS) diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 08ebd4e37da..a28bd5c2fd5 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -74,6 +74,12 @@ int rs6000_pic_labelno; /* Whether a System V.4 varargs area was created. */ int rs6000_sysv_varargs_p; +/* Whether we need to save the TOC register. */ +int rs6000_save_toc_p; + +/* ABI enumeration available for subtarget to use. */ +enum rs6000_abi rs6000_current_abi; + /* Temporary memory used to convert integer -> float */ static rtx stack_temps[NUM_MACHINE_MODES]; @@ -223,10 +229,19 @@ rs6000_override_options () {"601", PROCESSOR_PPC601, MASK_POWER | MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_MULTIPLE | MASK_STRING, MASK_POWER2 | POWERPC_OPT_MASKS | MASK_POWERPC64}, + {"602", PROCESSOR_PPC602, + MASK_POWER | MASK_POWERPC | MASK_NEW_MNEMONICS, + MASK_POWER2 | POWERPC_OPT_MASKS | MASK_POWERPC64}, {"603", PROCESSOR_PPC603, MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS, POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64}, + {"603e", PROCESSOR_PPC603, + MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS, + POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64}, {"604", PROCESSOR_PPC604, + MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS, + POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64}, + {"620", PROCESSOR_PPC620, MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS, POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64}}; @@ -350,6 +365,23 @@ any_operand (op, mode) return 1; } +/* Returns 1 if op is the count register */ +int count_register_operand(op, mode) + register rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != REG) + return 0; + + if (REGNO (op) == COUNT_REGISTER_REGNUM) + return 1; + + if (REGNO (op) > FIRST_PSEUDO_REGISTER) + return 1; + + return 0; +} + /* Return 1 if OP is a constant that can fit in a D field. */ int @@ -476,6 +508,10 @@ easy_fp_constant (op, mode) || GET_MODE_CLASS (mode) != MODE_FLOAT) return 0; + /* Consider all constants with -msoft-float to be easy */ + if (TARGET_SOFT_FLOAT) + return 1; + high = operand_subword (op, 0, 0, mode); low = operand_subword (op, 1, 0, mode); @@ -486,6 +522,34 @@ easy_fp_constant (op, mode) || (low != 0 && input_operand (low, word_mode))); } +/* Return 1 if the operand is in volatile memory. Note that during the + RTL generation phase, memory_operand does not return TRUE for + volatile memory references. So this function allows us to + recognize volatile references where its safe. */ + +int +volatile_mem_operand (op, mode) + register rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != MEM) + return 0; + + if (!MEM_VOLATILE_P (op)) + return 0; + + if (mode != GET_MODE (op)) + return 0; + + if (reload_completed) + return memory_operand (op, mode); + + if (reload_in_progress) + return strict_memory_address_p (mode, XEXP (op, 0)); + + return memory_address_p (mode, XEXP (op, 0)); +} + /* Return 1 if the operand is an offsettable memory address. */ int @@ -506,6 +570,7 @@ fp_reg_or_mem_operand (op, mode) enum machine_mode mode; { return (memory_operand (op, mode) + || volatile_mem_operand (op, mode) || (register_operand (op, mode) && (GET_CODE (op) != REG || REGNO (op) >= FIRST_PSEUDO_REGISTER @@ -640,7 +705,9 @@ reg_or_mem_operand (op, mode) register rtx op; register enum machine_mode mode; { - return gpc_reg_operand (op, mode) || memory_operand (op, mode); + return (gpc_reg_operand (op, mode) + || memory_operand (op, mode) + || volatile_mem_operand (op, mode)); } /* Return 1 if the operand is a general register or memory operand without @@ -732,6 +799,12 @@ input_operand (op, mode) if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (op)) return 1; + /* Windows NT allows SYMBOL_REFs and LABEL_REFs against the TOC + directly in the instruction stream */ + if (DEFAULT_ABI == ABI_NT + && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)) + return 1; + /* Otherwise, we will be doing this SET with an add, so anything valid for an add will be valid. */ return add_operand (op, mode); @@ -796,6 +869,26 @@ init_cumulative_args (cum, fntype, libname, incoming) } } +/* 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. + + Windows NT wants anything >= 8 bytes to be double word aligned. */ + +int +function_arg_boundary (mode, type) + enum machine_mode mode; + tree type; +{ + if (DEFAULT_ABI != ABI_NT || TARGET_64BIT) + return PARM_BOUNDARY; + + if (mode != BLKmode) + return (GET_MODE_SIZE (mode)) >= 8 ? 64 : 32; + + return (int_size_in_bytes (type) >= 8) ? 64 : 32; +} + /* 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.) */ @@ -807,6 +900,8 @@ function_arg_advance (cum, mode, type, named) tree type; int named; { + int align = ((cum->words & 1) != 0 && function_arg_boundary (mode, type) == 64) ? 1 : 0; + cum->words += align; cum->nargs_prototype--; #ifdef TARGET_V4_CALLS @@ -846,8 +941,8 @@ function_arg_advance (cum, mode, type, named) if (TARGET_DEBUG_ARG) fprintf (stderr, - "function_adv: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d\n", - cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named); + "function_adv: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d, align = %d\n", + cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named, align); } /* Determine where to put an argument to a function. @@ -880,10 +975,13 @@ function_arg (cum, mode, type, named) tree type; int named; { + int align = ((cum->words & 1) != 0 && function_arg_boundary (mode, type) == 64) ? 1 : 0; + int align_words = cum->words + align; + if (TARGET_DEBUG_ARG) fprintf (stderr, - "function_arg: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d\n", - cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named); + "function_arg: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, named = %d, align = %d\n", + cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), named, align); /* Return a marker to indicate whether CR1 needs to set or clear the bit that V.4 uses to say fp args were passed in registers. Assume that we don't need the @@ -920,8 +1018,8 @@ function_arg (cum, mode, type, named) return gen_rtx (REG, mode, cum->fregno); return gen_rtx (EXPR_LIST, VOIDmode, - ((cum->words < GP_ARG_NUM_REG) - ? gen_rtx (REG, mode, GP_ARG_MIN_REG + cum->words) + ((align_words < GP_ARG_NUM_REG) + ? gen_rtx (REG, mode, GP_ARG_MIN_REG + align_words) : NULL_RTX), gen_rtx (REG, mode, cum->fregno)); } @@ -929,14 +1027,14 @@ function_arg (cum, mode, type, named) #ifdef TARGET_V4_CALLS /* Long longs won't be split between register and stack */ else if (TARGET_V4_CALLS && - cum->words + RS6000_ARG_SIZE (mode, type, named) > GP_ARG_NUM_REG) + align_words + RS6000_ARG_SIZE (mode, type, named) > GP_ARG_NUM_REG) { return NULL_RTX; } #endif - else if (cum->words < GP_ARG_NUM_REG) - return gen_rtx (REG, mode, GP_ARG_MIN_REG + cum->words); + else if (align_words < GP_ARG_NUM_REG) + return gen_rtx (REG, mode, GP_ARG_MIN_REG + align_words); return NULL_RTX; } @@ -1164,8 +1262,13 @@ expand_block_move_mem (mode, addr, orig_mem) rtx orig_mem; { rtx mem = gen_rtx (MEM, mode, addr); + + RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (orig_mem); MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (orig_mem); MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (orig_mem); +#ifdef MEM_UNALIGNED_P + MEM_UNALIGNED_P (mem) = MEM_UNALIGNED_P (orig_mem); +#endif return mem; } @@ -1183,6 +1286,8 @@ int expand_block_move (operands) rtx operands[]; { + rtx orig_dest = operands[0]; + rtx orig_src = operands[1]; rtx bytes_rtx = operands[2]; rtx align_rtx = operands[3]; int constp = (GET_CODE (bytes_rtx) == CONST_INT); @@ -1224,8 +1329,8 @@ expand_block_move (operands) return 0; /* Move the address into scratch registers. */ - dest_reg = copy_addr_to_reg (XEXP (operands[0], 0)); - src_reg = copy_addr_to_reg (XEXP (operands[1], 0)); + dest_reg = copy_addr_to_reg (XEXP (orig_dest, 0)); + src_reg = copy_addr_to_reg (XEXP (orig_src, 0)); if (TARGET_STRING) /* string instructions are available */ { @@ -1242,8 +1347,8 @@ expand_block_move (operands) && !fixed_regs[12]) { move_bytes = (bytes > 32) ? 32 : bytes; - emit_insn (gen_movstrsi_8reg (dest_reg, - src_reg, + emit_insn (gen_movstrsi_8reg (expand_block_move_mem (BLKmode, dest_reg, orig_dest), + expand_block_move_mem (BLKmode, src_reg, orig_src), GEN_INT ((move_bytes == 32) ? 0 : move_bytes), align_rtx)); } @@ -1256,8 +1361,8 @@ expand_block_move (operands) && !fixed_regs[12]) { move_bytes = (bytes > 24) ? 24 : bytes; - emit_insn (gen_movstrsi_6reg (dest_reg, - src_reg, + emit_insn (gen_movstrsi_6reg (expand_block_move_mem (BLKmode, dest_reg, orig_dest), + expand_block_move_mem (BLKmode, src_reg, orig_src), GEN_INT (move_bytes), align_rtx)); } @@ -1268,16 +1373,16 @@ expand_block_move (operands) && !fixed_regs[12]) { move_bytes = (bytes > 16) ? 16 : bytes; - emit_insn (gen_movstrsi_4reg (dest_reg, - src_reg, + emit_insn (gen_movstrsi_4reg (expand_block_move_mem (BLKmode, dest_reg, orig_dest), + expand_block_move_mem (BLKmode, src_reg, orig_src), GEN_INT (move_bytes), align_rtx)); } else if (bytes > 4 && !TARGET_64BIT) { /* move up to 8 bytes at a time */ move_bytes = (bytes > 8) ? 8 : bytes; - emit_insn (gen_movstrsi_2reg (dest_reg, - src_reg, + emit_insn (gen_movstrsi_2reg (expand_block_move_mem (BLKmode, dest_reg, orig_dest), + expand_block_move_mem (BLKmode, src_reg, orig_src), GEN_INT (move_bytes), align_rtx)); } @@ -1285,28 +1390,28 @@ expand_block_move (operands) { /* move 4 bytes */ move_bytes = 4; tmp_reg = gen_reg_rtx (SImode); - emit_move_insn (tmp_reg, gen_rtx (MEM, SImode, src_reg)); - emit_move_insn (gen_rtx (MEM, SImode, dest_reg), tmp_reg); + emit_move_insn (tmp_reg, expand_block_move_mem (SImode, src_reg, orig_src)); + emit_move_insn (expand_block_move_mem (SImode, dest_reg, orig_dest), tmp_reg); } else if (bytes == 2 && (align >= 2 || !STRICT_ALIGNMENT)) { /* move 2 bytes */ move_bytes = 2; tmp_reg = gen_reg_rtx (HImode); - emit_move_insn (tmp_reg, gen_rtx (MEM, HImode, src_reg)); - emit_move_insn (gen_rtx (MEM, HImode, dest_reg), tmp_reg); + emit_move_insn (tmp_reg, expand_block_move_mem (HImode, src_reg, orig_src)); + emit_move_insn (expand_block_move_mem (HImode, dest_reg, orig_dest), tmp_reg); } else if (bytes == 1) /* move 1 byte */ { move_bytes = 1; tmp_reg = gen_reg_rtx (QImode); - emit_move_insn (tmp_reg, gen_rtx (MEM, QImode, src_reg)); - emit_move_insn (gen_rtx (MEM, QImode, dest_reg), tmp_reg); + emit_move_insn (tmp_reg, expand_block_move_mem (QImode, src_reg, orig_src)); + emit_move_insn (expand_block_move_mem (QImode, dest_reg, orig_dest), tmp_reg); } else { /* move up to 4 bytes at a time */ move_bytes = (bytes > 4) ? 4 : bytes; - emit_insn (gen_movstrsi_1reg (dest_reg, - src_reg, + emit_insn (gen_movstrsi_1reg (expand_block_move_mem (BLKmode, dest_reg, orig_dest), + expand_block_move_mem (BLKmode, src_reg, orig_src), GEN_INT (move_bytes), align_rtx)); } @@ -1337,26 +1442,33 @@ expand_block_move (operands) } /* Generate the appropriate load and store, saving the stores for later */ - if (bytes >= 4 && (align >= 4 || !STRICT_ALIGNMENT)) + if (bytes >= 8 && TARGET_64BIT && (align >= 8 || !STRICT_ALIGNMENT)) + { + move_bytes = 8; + tmp_reg = gen_reg_rtx (DImode); + emit_insn (gen_movdi (tmp_reg, expand_block_move_mem (DImode, src_addr, orig_src))); + stores[ num_reg++ ] = gen_movdi (expand_block_move_mem (DImode, dest_addr, orig_dest), tmp_reg); + } + else if (bytes >= 4 && (align >= 4 || !STRICT_ALIGNMENT)) { move_bytes = 4; tmp_reg = gen_reg_rtx (SImode); - emit_insn (gen_movsi (tmp_reg, gen_rtx (MEM, SImode, src_addr))); - stores[ num_reg++ ] = gen_movsi (gen_rtx (MEM, SImode, dest_addr), tmp_reg); + emit_insn (gen_movsi (tmp_reg, expand_block_move_mem (SImode, src_addr, orig_src))); + stores[ num_reg++ ] = gen_movsi (expand_block_move_mem (SImode, dest_addr, orig_dest), tmp_reg); } else if (bytes >= 2 && (align >= 2 || !STRICT_ALIGNMENT)) { move_bytes = 2; tmp_reg = gen_reg_rtx (HImode); - emit_insn (gen_movhi (tmp_reg, gen_rtx (MEM, HImode, src_addr))); - stores[ num_reg++ ] = gen_movhi (gen_rtx (MEM, HImode, dest_addr), tmp_reg); + emit_insn (gen_movsi (tmp_reg, expand_block_move_mem (HImode, src_addr, orig_src))); + stores[ num_reg++ ] = gen_movhi (expand_block_move_mem (HImode, dest_addr, orig_dest), tmp_reg); } else { move_bytes = 1; tmp_reg = gen_reg_rtx (QImode); - emit_insn (gen_movqi (tmp_reg, gen_rtx (MEM, QImode, src_addr))); - stores[ num_reg++ ] = gen_movqi (gen_rtx (MEM, QImode, dest_addr), tmp_reg); + emit_insn (gen_movsi (tmp_reg, expand_block_move_mem (QImode, src_addr, orig_src))); + stores[ num_reg++ ] = gen_movqi (expand_block_move_mem (QImode, dest_addr, orig_dest), tmp_reg); } if (num_reg >= MAX_MOVE_REG) @@ -1367,11 +1479,8 @@ expand_block_move (operands) } } - if (num_reg > 0) - { - for (i = 0; i < num_reg; i++) - emit_insn (stores[i]); - } + for (i = 0; i < num_reg; i++) + emit_insn (stores[i]); } return 1; @@ -2127,9 +2236,26 @@ print_operand (file, x, code) if (GET_CODE (x) != SYMBOL_REF) abort (); -#ifndef USING_SVR4_H - putc ('.', file); -#endif + if (XSTR (x, 0)[0] != '.') + { + switch (DEFAULT_ABI) + { + default: + abort (); + + case ABI_AIX: + putc ('.', file); + break; + + case ABI_V4: + case ABI_AIX_NODESC: + break; + + case ABI_NT: + fputs ("..", file); + break; + } + } RS6000_OUTPUT_BASENAME (file, XSTR (x, 0)); return; @@ -2235,11 +2361,9 @@ first_reg_to_save () to 23 to do this. Don't use the frame pointer in reg 31. For now, save enough room for all of the parameter registers. */ -#ifndef USING_SVR4_H - if (profile_flag) + if (DEFAULT_ABI == ABI_AIX && profile_flag) if (first_reg > 23) first_reg = 23; -#endif return first_reg; } @@ -2333,7 +2457,49 @@ rs6000_makes_calls () +---------------------------------------+ old SP->| back chain to caller's caller | +---------------------------------------+ -*/ + + + A PowerPC Windows/NT frame looks like: + + SP----> +---------------------------------------+ + | back chain to caller | 0 + +---------------------------------------+ + | reserved | 4 + +---------------------------------------+ + | reserved | 8 + +---------------------------------------+ + | reserved | 12 + +---------------------------------------+ + | reserved | 16 + +---------------------------------------+ + | reserved | 20 + +---------------------------------------+ + | Parameter save area (P) | 24 + +---------------------------------------+ + | Alloca space (A) | 24+P + +---------------------------------------+ + | Local variable space (L) | 24+P+A + +---------------------------------------+ + | Save area for FP registers (F) | 24+P+A+L + +---------------------------------------+ + | Possible alignment area (X) | 24+P+A+L+F + +---------------------------------------+ + | Save area for GP registers (G) | 24+P+A+L+F+X + +---------------------------------------+ + | Save area for CR (C) | 24+P+A+L+F+X+G + +---------------------------------------+ + | Save area for TOC (T) | 24+P+A+L+F+X+G+C + +---------------------------------------+ + | Save area for LR (R) | 24+P+A+L+F+X+G+C+T + +---------------------------------------+ + old SP->| back chain to caller's caller | + +---------------------------------------+ + + For NT, there is no specific order to save the registers, but in + order to support __builtin_return_address, the save area for the + link register needs to be in a known place, so we use -4 off of the + old SP. To support calls through pointers, we also allocate a + fixed slot to store the TOC, -8 off the old SP. */ rs6000_stack_t * rs6000_stack_info () @@ -2342,19 +2508,13 @@ rs6000_stack_info () rs6000_stack_t *info_ptr = &info; int reg_size = TARGET_64BIT ? 8 : 4; enum rs6000_abi abi; + int total_raw_size; /* Zero all fields portably */ info = zero_info; /* Select which calling sequence */ -#ifdef TARGET_V4_CALLS - if (TARGET_V4_CALLS) - abi = ABI_V4; - else -#endif - abi = ABI_AIX; - - info_ptr->abi = abi; + info_ptr->abi = abi = DEFAULT_ABI; /* Calculate which registers need to be saved & save area size */ info_ptr->first_gp_reg_save = first_reg_to_save (); @@ -2366,6 +2526,39 @@ rs6000_stack_info () /* Does this function call anything? */ info_ptr->calls_p = rs6000_makes_calls (); + /* Do we need to allocate space to save the toc? */ + if (rs6000_save_toc_p) + { + info_ptr->toc_save_p = 1; + info_ptr->toc_size = reg_size; + } + + /* If this is main and we need to call a function to set things up, + save main's arguments around the call. */ + if (strcmp (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)), "main") == 0) + { + info_ptr->main_p = 1; + +#ifdef NAME__MAIN + if (DECL_ARGUMENTS (current_function_decl)) + { + int i; + tree arg; + + info_ptr->main_save_p = 1; + info_ptr->main_size = 0; + info_ptr->calls_p = 1; + + for ((i = 0), (arg = DECL_ARGUMENTS (current_function_decl)); + arg != NULL_TREE && i < 8; + (arg = TREE_CHAIN (arg)), i++) + { + info_ptr->main_size += reg_size; + } + } +#endif + } + /* Determine if we need to save the link register */ if (regs_ever_live[65] || profile_flag #ifdef TARGET_RELOCATABLE @@ -2378,13 +2571,15 @@ rs6000_stack_info () { info_ptr->lr_save_p = 1; regs_ever_live[65] = 1; + if (abi == ABI_NT) + info_ptr->lr_size = reg_size; } /* Determine if we need to save the condition code registers */ if (regs_ever_live[70] || regs_ever_live[71] || regs_ever_live[72]) { info_ptr->cr_save_p = 1; - if (abi == ABI_V4) + if (abi == ABI_V4 || abi == ABI_NT) info_ptr->cr_size = reg_size; } @@ -2394,12 +2589,20 @@ rs6000_stack_info () info_ptr->varargs_size = RS6000_VARARGS_AREA; info_ptr->vars_size = ALIGN (get_frame_size (), 8); info_ptr->parm_size = ALIGN (current_function_outgoing_args_size, 8); - info_ptr->save_size = ALIGN (info_ptr->fp_size + info_ptr->gp_size + info_ptr->cr_size, 8); - info_ptr->total_size = ALIGN (info_ptr->vars_size - + info_ptr->parm_size - + info_ptr->save_size - + info_ptr->varargs_size - + info_ptr->fixed_size, STACK_BOUNDARY / BITS_PER_UNIT); + info_ptr->save_size = ALIGN (info_ptr->fp_size + + info_ptr->gp_size + + info_ptr->cr_size + + info_ptr->lr_size + + info_ptr->toc_size + + info_ptr->main_size, 8); + + total_raw_size = (info_ptr->vars_size + + info_ptr->parm_size + + info_ptr->save_size + + info_ptr->varargs_size + + info_ptr->fixed_size); + + info_ptr->total_size = ALIGN (total_raw_size, STACK_BOUNDARY / BITS_PER_UNIT); /* Determine if we need to allocate any stack frame. For AIX We need to push the stack if a frame pointer is needed (because @@ -2412,8 +2615,8 @@ rs6000_stack_info () if (info_ptr->calls_p) info_ptr->push_p = 1; - else if (abi == ABI_V4) - info_ptr->push_p = (info_ptr->total_size > info_ptr->fixed_size + else if (abi == ABI_V4 || abi == ABI_NT) + info_ptr->push_p = (total_raw_size > info_ptr->fixed_size || info_ptr->lr_save_p); else @@ -2422,18 +2625,40 @@ rs6000_stack_info () || info_ptr->total_size > 220); /* Calculate the offsets */ - info_ptr->fp_save_offset = - info_ptr->fp_size; - info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size; switch (abi) { + case ABI_NONE: default: - info_ptr->cr_save_offset = 4; - info_ptr->lr_save_offset = 8; + abort (); + + case ABI_AIX: + case ABI_AIX_NODESC: + info_ptr->fp_save_offset = - info_ptr->fp_size; + info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size; + info_ptr->main_save_offset = info_ptr->gp_save_offset - info_ptr->main_size; + info_ptr->cr_save_offset = 4; + info_ptr->lr_save_offset = 8; break; case ABI_V4: - info_ptr->cr_save_offset = info_ptr->gp_save_offset - reg_size; - info_ptr->lr_save_offset = reg_size; + info_ptr->fp_save_offset = - info_ptr->fp_size; + info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size; + info_ptr->cr_save_offset = info_ptr->gp_save_offset - reg_size; + info_ptr->toc_save_offset = info_ptr->cr_save_offset - info_ptr->cr_size; + info_ptr->main_save_offset = info_ptr->toc_save_offset - info_ptr->toc_size; + info_ptr->lr_save_offset = reg_size; + break; + + case ABI_NT: + info_ptr->lr_save_offset = -4; + info_ptr->toc_save_offset = info_ptr->lr_save_offset - info_ptr->lr_size; + info_ptr->cr_save_offset = info_ptr->toc_save_offset - info_ptr->toc_size; + info_ptr->gp_save_offset = info_ptr->cr_save_offset - info_ptr->cr_size - info_ptr->gp_size + reg_size; + info_ptr->fp_save_offset = info_ptr->gp_save_offset - info_ptr->fp_size; + if (info_ptr->fp_size && ((- info_ptr->fp_save_offset) % 8) != 0) + info_ptr->fp_save_offset -= 4; + + info_ptr->main_save_offset = info_ptr->fp_save_offset - info_ptr->main_size; break; } @@ -2450,6 +2675,12 @@ rs6000_stack_info () if (!info_ptr->cr_save_p) info_ptr->cr_save_offset = 0; + if (!info_ptr->toc_save_p) + info_ptr->toc_save_offset = 0; + + if (!info_ptr->main_save_p) + info_ptr->main_save_offset = 0; + return info_ptr; } @@ -2469,10 +2700,12 @@ debug_stack_info (info) switch (info->abi) { - default: abi_string = "Unknown"; break; - case ABI_NONE: abi_string = "NONE"; break; - case ABI_AIX: abi_string = "AIX"; break; - case ABI_V4: abi_string = "V.4"; break; + default: abi_string = "Unknown"; break; + case ABI_NONE: abi_string = "NONE"; break; + case ABI_AIX: abi_string = "AIX"; break; + case ABI_AIX_NODESC: abi_string = "AIX"; break; + case ABI_V4: abi_string = "V.4"; break; + case ABI_NT: abi_string = "NT"; break; } fprintf (stderr, "\tABI = %5s\n", abi_string); @@ -2489,12 +2722,21 @@ debug_stack_info (info) if (info->cr_save_p) fprintf (stderr, "\tcr_save_p = %5d\n", info->cr_save_p); + if (info->toc_save_p) + fprintf (stderr, "\ttoc_save_p = %5d\n", info->toc_save_p); + if (info->push_p) fprintf (stderr, "\tpush_p = %5d\n", info->push_p); if (info->calls_p) fprintf (stderr, "\tcalls_p = %5d\n", info->calls_p); + if (info->main_p) + fprintf (stderr, "\tmain_p = %5d\n", info->main_p); + + if (info->main_save_p) + fprintf (stderr, "\tmain_save_p = %5d\n", info->main_save_p); + if (info->gp_save_offset) fprintf (stderr, "\tgp_save_offset = %5d\n", info->gp_save_offset); @@ -2507,9 +2749,15 @@ debug_stack_info (info) if (info->cr_save_offset) fprintf (stderr, "\tcr_save_offset = %5d\n", info->cr_save_offset); + if (info->toc_save_offset) + fprintf (stderr, "\ttoc_save_offset = %5d\n", info->toc_save_offset); + if (info->varargs_save_offset) fprintf (stderr, "\tvarargs_save_offset = %5d\n", info->varargs_save_offset); + if (info->main_save_offset) + fprintf (stderr, "\tmain_save_offset = %5d\n", info->main_save_offset); + if (info->total_size) fprintf (stderr, "\ttotal_size = %5d\n", info->total_size); @@ -2531,9 +2779,18 @@ debug_stack_info (info) if (info->fp_size) fprintf (stderr, "\tfp_size = %5d\n", info->fp_size); + if (info->lr_size) + fprintf (stderr, "\tlr_size = %5d\n", info->cr_size); + if (info->cr_size) fprintf (stderr, "\tcr_size = %5d\n", info->cr_size); + if (info->toc_size) + fprintf (stderr, "\ttoc_size = %5d\n", info->toc_size); + + if (info->main_size) + fprintf (stderr, "\tmain_size = %5d\n", info->main_size); + if (info->save_size) fprintf (stderr, "\tsave_size = %5d\n", info->save_size); @@ -2543,65 +2800,6 @@ debug_stack_info (info) fprintf (stderr, "\n"); } - - -#ifdef USING_SVR4_H -/* Write out a System V.4 style traceback table before the prologue - - At present, only emit the basic tag table (ie, do not emit tag_types other - than 0, which might use more than 1 tag word). - - The first tag word looks like: - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | 0 |ver| tag |e|s| alloca | # fprs | # gprs |s|l|c|f| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -*/ - -void -svr4_traceback (file, name, decl) - FILE *file; - tree name, decl; -{ - rs6000_stack_t *info = rs6000_stack_info (); - long tag; - long version = 0; /* version number */ - long tag_type = 0; /* function type */ - long extended_tag = 0; /* additional tag words needed */ - long spare = 0; /* reserved for future use */ - long fpscr_max = 0; /* 1 if the function has a FPSCR save word */ - long fpr_max = 64 - info->first_fp_reg_save; /* # of floating point registers saved */ - long gpr_max = 32 - info->first_gp_reg_save; /* # of general purpose registers saved */ - long alloca_reg; /* stack/frame register */ - - if (frame_pointer_needed) - alloca_reg = 31; - - else if (info->push_p != 0) - alloca_reg = 1; - - else - alloca_reg = 0; - - tag = ((version << 24) - | (tag_type << 21) - | (extended_tag << 20) - | (spare << 19) - | (alloca_reg << 14) - | (fpr_max << 9) - | (gpr_max << 4) - | (info->push_p << 3) - | (info->lr_save_p << 2) - | (info->cr_save_p << 1) - | (fpscr_max << 0)); - - fprintf (file, "\t.long 0x%lx\n", tag); -} - -#endif /* USING_SVR4_H */ /* Write function prologue. */ void @@ -2610,19 +2808,30 @@ output_prolog (file, size) int size; { rs6000_stack_t *info = rs6000_stack_info (); - char *store_reg = (TARGET_64BIT) ? "\tstd %s,%d(%s)" : "\t{st|stw} %s,%d(%s)\n"; + int reg_size = info->reg_size; + char *store_reg; + char *load_reg; + + if (TARGET_64BIT) + { + store_reg = "\tstd %s,%d(%s)"; + load_reg = "\tlld %s,%d(%s)"; + } + else + { + store_reg = "\t{st|stw} %s,%d(%s)\n"; + load_reg = "\t{l|lwz} %s,%d(%s)\n"; + } if (TARGET_DEBUG_STACK) debug_stack_info (info); /* Write .extern for any function we will call to save and restore fp values. */ -#ifndef USING_SVR4_H - if (info->first_fp_reg_save < 62) + if (info->first_fp_reg_save < 64 && !FP_SAVE_INLINE (info->first_fp_reg_save)) fprintf (file, "\t.extern %s%d%s\n\t.extern %s%d%s\n", SAVE_FP_PREFIX, info->first_fp_reg_save - 32, SAVE_FP_SUFFIX, RESTORE_FP_PREFIX, info->first_fp_reg_save - 32, RESTORE_FP_SUFFIX); -#endif /* Write .extern for truncation routines, if needed. */ if (rs6000_trunc_used && ! trunc_defined) @@ -2672,7 +2881,6 @@ output_prolog (file, size) { int regno = info->first_gp_reg_save; int loc = info->gp_save_offset; - int reg_size = (TARGET_64BIT) ? 8 : 4; for ( ; regno < 32; regno++, loc += reg_size) asm_fprintf (file, store_reg, reg_names[regno], loc, reg_names[1]); @@ -2684,6 +2892,19 @@ output_prolog (file, size) info->gp_save_offset, reg_names[1]); + /* Save main's arguments if we need to call a function */ +#ifdef NAME__MAIN + if (info->main_save_p) + { + int regno; + int loc = info->main_save_offset; + int size = info->main_size; + + for (regno = 3; size > 0; regno++, loc -= reg_size, size -= reg_size) + asm_fprintf (file, store_reg, reg_names[regno], loc, reg_names[1]); + } +#endif + /* Save lr if we used it. */ if (info->lr_save_p) asm_fprintf (file, store_reg, reg_names[0], info->lr_save_offset, reg_names[1]); @@ -2692,6 +2913,9 @@ output_prolog (file, size) if (info->cr_save_p) asm_fprintf (file, store_reg, reg_names[12], info->cr_save_offset, reg_names[1]); + if (info->toc_save_p) + asm_fprintf (file, store_reg, reg_names[2], info->toc_save_offset, reg_names[1]); + /* Update stack and set back pointer. */ if (info->push_p) { @@ -2715,13 +2939,62 @@ output_prolog (file, size) if (frame_pointer_needed) asm_fprintf (file, "\tmr %s,%s\n", reg_names[31], reg_names[1]); +#ifdef NAME__MAIN + /* If we need to call a function to set things up for main, do so now + before dealing with the TOC. */ + if (info->main_p) + { + char *prefix = ""; + + switch (DEFAULT_ABI) + { + case ABI_AIX: prefix = "."; break; + case ABI_NT: prefix = ".."; break; + } + + fprintf (file, "\tbl %s%s\n", prefix, NAME__MAIN); +#ifdef RS6000_CALL_GLUE2 + fprintf (file, "\t%s%s%s\n", RS6000_CALL_GLUE2, prefix, NAME_MAIN); +#else +#ifdef RS6000_CALL_GLUE + if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT) + fprintf (file, "\t%s\n", RS6000_CALL_GLUE); +#endif +#endif + + if (info->main_save_p) + { + int regno; + int loc; + int size = info->main_size; + + if (info->total_size < 32767) + { + loc = info->total_size + info->main_save_offset; + for (regno = 3; size > 0; regno++, size -= reg_size, loc -= reg_size) + asm_fprintf (file, load_reg, reg_names[regno], loc, reg_names[1]); + } + else + { /* for large frames, reg 0 above contains -frame size */ + loc = info->main_save_offset; + asm_fprintf (file, "\t{sf|subf} %s,%s,%s\n", reg_names[0], reg_names[0], + reg_names[1]); + + for (regno = 3; size > 0; regno++, size -= reg_size, loc -= reg_size) + asm_fprintf (file, load_reg, reg_names[regno], loc, reg_names[0]); + } + } + } +#endif + + /* If TARGET_MINIMAL_TOC, and the constant pool is needed, then load the TOC_TABLE address into register 30. */ if (TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0) { char buf[256]; -#ifdef USING_SVR4_H +#ifdef TARGET_RELOCATABLE if (TARGET_RELOCATABLE) { ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno); @@ -2732,13 +3005,7 @@ output_prolog (file, size) ASM_OUTPUT_INTERNAL_LABEL (file, "LCF", rs6000_pic_labelno); fprintf (file, "\tmflr %s\n", reg_names[30]); - if (TARGET_POWERPC64) - fprintf (file, "\tld"); - else if (TARGET_NEW_MNEMONICS) - fprintf (file, "\tlwz"); - else - fprintf (file, "\tl"); - + asm_fprintf (file, TARGET_64BIT ? "\tld" : "\t{l|lwz}"); fprintf (file, " %s,(", reg_names[0]); ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_labelno); assemble_name (file, buf); @@ -2750,34 +3017,51 @@ output_prolog (file, size) reg_names[30], reg_names[0], reg_names[30]); rs6000_pic_labelno++; } - else if (!TARGET_64BIT) - { - ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1); - asm_fprintf (file, "\t{cau|addis} %s,%s,", reg_names[30], reg_names[0]); + else +#endif + + switch (DEFAULT_ABI) + { + case ABI_V4: + case ABI_AIX_NODESC: + if (!TARGET_64BIT) + { + ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1); + asm_fprintf (file, "\t{cau|addis} %s,%s,", reg_names[30], reg_names[0]); + assemble_name (file, buf); + asm_fprintf (file, "@ha\n"); + if (TARGET_NEW_MNEMONICS) + { + asm_fprintf (file, "\taddi %s,%s,", reg_names[30], reg_names[30]); + assemble_name (file, buf); + asm_fprintf (file, "@l\n"); + } + else + { + asm_fprintf (file, "\tcal %s,", reg_names[30]); + assemble_name (file, buf); + asm_fprintf (file, "@l(%s)\n", reg_names[30]); + } + } + else + abort (); + + break; + + case ABI_NT: + case ABI_AIX: + ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 0); + asm_fprintf (file, "\t{l|lwz} %s,", reg_names[30]); assemble_name (file, buf); - asm_fprintf (file, "@ha\n"); - if (TARGET_NEW_MNEMONICS) - { - asm_fprintf (file, "\taddi %s,%s,", reg_names[30], reg_names[30]); - assemble_name (file, buf); - asm_fprintf (file, "@l\n"); - } - else - { - asm_fprintf (file, "\tcal %s,", reg_names[30]); - assemble_name (file, buf); - asm_fprintf (file, "@l(%s)\n", reg_names[30]); - } + asm_fprintf (file, "(%s)\n", reg_names[2]); + break; } - else - abort (); + } -#else /* !USING_SVR4_H */ - ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 0); - asm_fprintf (file, "\t{l|lwz} %s,", reg_names[30]); - assemble_name (file, buf); - asm_fprintf (file, "(%s)\n", reg_names[2]); -#endif /* USING_SVR4_H */ + if (DEFAULT_ABI == ABI_NT) + { + assemble_name (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); + fputs (".b:\n", file); } } @@ -2886,14 +3170,16 @@ output_epilog (file, size) traceback table itself. System V.4 Powerpc's (and the embedded ABI derived from it) use a - different traceback table located before the prologue. */ -#ifndef USING_SVR4_H - if (! flag_inhibit_size_directive) + different traceback table. */ + if (DEFAULT_ABI == ABI_AIX && ! flag_inhibit_size_directive) { char *fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0); int fixed_parms, float_parms, parm_info; int i; + while (*fname == '.') /* V.4 encodes . in the name */ + fname++; + /* Need label immediately before tbtab, so we can compute its offset from the function start. */ if (*fname == '*') @@ -3065,10 +3351,18 @@ output_epilog (file, size) if (frame_pointer_needed) fprintf (file, "\t.byte 31\n"); } -#endif /* !USING_SVR4_H */ - /* Reset varargs indicator */ + /* Reset varargs and save TOC indicator */ rs6000_sysv_varargs_p = 0; + rs6000_save_toc_p = 0; + + if (DEFAULT_ABI == ABI_NT) + { + RS6000_OUTPUT_BASENAME (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); + fputs (".e:\nFE_MOT_RESVD..", file); + RS6000_OUTPUT_BASENAME (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); + fputs (":\n", file); + } } /* Output a TOC entry. We derive the entry name from what is @@ -3082,6 +3376,7 @@ output_toc (file, x, labelno) { char buf[256]; char *name = buf; + char *real_name; rtx base = x; int offset = 0; @@ -3098,8 +3393,7 @@ output_toc (file, x, labelno) } -#ifdef USING_SVR4_H - if (TARGET_MINIMAL_TOC) + if (TARGET_ELF && TARGET_MINIMAL_TOC) { ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LC"); fprintf (file, "%d = .-", labelno); @@ -3107,7 +3401,6 @@ output_toc (file, x, labelno) fprintf (file, "1\n"); } else -#endif /* USING_SVR4_H */ ASM_OUTPUT_INTERNAL_LABEL (file, "LC", labelno); /* Handle FP constants specially. Note that if we have a minimal @@ -3163,8 +3456,8 @@ output_toc (file, x, labelno) fprintf (file, "\t.long "); else { - fprintf (file, "\t.tc "); - RS6000_OUTPUT_BASENAME (file, name); + STRIP_NAME_ENCODING (real_name, name); + fprintf (file, "\t.tc %s", real_name); if (offset < 0) fprintf (file, ".N%d", - offset); @@ -3309,14 +3602,14 @@ output_function_profiler (file, labelno) FILE *file; int labelno; { -#ifdef USING_SVR4_H - abort (); -#else /* The last used parameter register. */ int last_parm_reg; int i, j; char buf[100]; + if (DEFAULT_ABI != ABI_AIX) + abort (); + /* Set up a TOC entry for the profiler label. */ toc_section (); ASM_OUTPUT_INTERNAL_LABEL (file, "LPC", labelno); @@ -3363,7 +3656,6 @@ output_function_profiler (file, labelno) for (i = 3, j = 30; i <= last_parm_reg; i++, j--) fprintf (file, "\tai %d,%d,0\n", i, j); -#endif } /* Adjust the cost of a scheduling dependency. Return the new cost of @@ -3399,3 +3691,275 @@ rs6000_adjust_cost (insn, link, dep_insn, cost) return cost; } + +/* Return how many instructions the machine can issue per cycle */ +int get_issue_rate() +{ + switch (rs6000_cpu_attr) { + case CPU_RIOS1: + return 3; /* ? */ + case CPU_RIOS2: + return 4; + case CPU_PPC601: + return 3; /* ? */ + case CPU_PPC602: + return 1; + case CPU_PPC603: + return 2; + case CPU_PPC604: + return 4; + case CPU_PPC620: + return 4; + default: + return 1; + } +} + + +/* Output insns to flush the {data|instruction} caches after building a + trampoline. */ + +static void +rs6000_sync_trampoline (addr) + rtx addr; +{ + enum machine_mode pmode = Pmode; + rtx reg = gen_reg_rtx (pmode); + rtx mem2; + rtx mem1; + int size = rs6000_trampoline_size (); + rtx (*sub_fcn) PROTO ((rtx, rtx, rtx)); + rtx (*cmp_fcn) PROTO ((rtx, rtx)); + rtx label; + + if (TARGET_64BIT) + { + abort (); /* no cmpdi function yet */ + } + else + { + sub_fcn = gen_subsi3; + cmp_fcn = gen_cmpsi; + } + + addr = force_reg (pmode, addr); + mem2 = gen_rtx (MEM, pmode, gen_rtx (PLUS, pmode, addr, reg)); + mem1 = gen_rtx (MEM, pmode, addr); + + /* Issue a loop of dcbst's to flush the data cache */ + emit_move_insn (reg, GEN_INT (size-4)); + label = gen_label_rtx (); + emit_label (label); + emit_insn (gen_dcbst (mem2, addr, reg)); + emit_insn ((*sub_fcn) (reg, reg, GEN_INT (4))); + emit_insn ((*cmp_fcn) (reg, const0_rtx)); + emit_jump_insn (gen_bgt (label)); + + /* Issue a sync after the dcbst's to let things settle down */ + emit_insn (gen_sync (mem1)); + + /* Issue a loop of icbi's to flush the instruction cache */ + emit_move_insn (reg, GEN_INT (size-4)); + label = gen_label_rtx (); + emit_label (label); + emit_insn (gen_icbi (mem2, addr, reg)); + emit_insn ((*sub_fcn) (reg, reg, GEN_INT (4))); + emit_insn ((*cmp_fcn) (reg, const0_rtx)); + emit_jump_insn (gen_bgt (label)); + + /* Issue a sync after the icbi's to let things settle down */ + emit_insn (gen_sync (mem1)); + + /* Finally issue an isync to synchronize the icache */ + emit_insn (gen_isync (mem1)); +} + + +/* Output assembler code for a block containing the constant parts + of a trampoline, leaving space for the variable parts. + + The trampoline should set the static chain pointer to value placed + into the trampoline and should branch to the specified routine. */ + +void +rs6000_trampoline_template (file) + FILE *file; +{ + char *sc = reg_names[STATIC_CHAIN_REGNUM]; + char *r0 = reg_names[0]; + + switch (DEFAULT_ABI) + { + default: + abort (); + + /* Under AIX, this is not code at all, but merely a data area, + since that is the way all functions are called. The first word is + the address of the function, the second word is the TOC pointer (r2), + and the third word is the static chain value. */ + case ABI_AIX: + fprintf (file, "\t.long %s\n", (TARGET_64BIT) ? "0,0,0,0,0,0" : "0,0,0"); + break; + + + /* V.4/eabi function pointers are just a single pointer, so we need to + do the full gory code to load up the static chain. */ + case ABI_V4: + case ABI_AIX_NODESC: + if (STATIC_CHAIN_REGNUM == 0 || !TARGET_NEW_MNEMONICS) + abort (); + + if (TARGET_64BIT) + { + fprintf (file, "\tmflr %s\n", r0); /* offset 0 */ + fprintf (file, "\tbl .LTRAMP1\n"); /* offset 4 */ + fprintf (file, "\t.long 0,0,0,0\n"); /* offset 8 */ + fprintf (file, ".LTRAMP1:\n"); + fprintf (file, "\tmflr %s\n", sc); /* offset 28 */ + fprintf (file, "\tmtlr %s\n", r0); /* offset 32 */ + fprintf (file, "\tld %s,0(%s)\n", r0, sc); /* offset 36 */ + fprintf (file, "\tld %s,8(%s)\n", sc, sc); /* offset 40 */ + fprintf (file, "\tmtctr %s\n", r0); /* offset 44 */ + fprintf (file, "\tbctr\n"); /* offset 48 */ + } + else + { + fprintf (file, "\tmflr %s\n", r0); /* offset 0 */ + fprintf (file, "\tbl .LTRAMP1\n"); /* offset 4 */ + fprintf (file, "\t.long 0,0\n"); /* offset 8 */ + fprintf (file, ".LTRAMP1:\n"); + fprintf (file, "\tmflr %s\n", sc); /* offset 20 */ + fprintf (file, "\tmtlr %s\n", r0); /* offset 24 */ + fprintf (file, "\tlwz %s,0(%s)\n", r0, sc); /* offset 28 */ + fprintf (file, "\tlwz %s,4(%s)\n", sc, sc); /* offset 32 */ + fprintf (file, "\tmtctr %s\n", r0); /* offset 36 */ + fprintf (file, "\tbctr\n"); /* offset 40 */ + } + break; + + /* NT function pointers point to a two word area (real address, TOC) + which unfortunately does not include a static chain field. So we + need to have a 2 word area followed by the code to load up the + static chain. */ + case ABI_NT: + if (STATIC_CHAIN_REGNUM == 0 || !TARGET_NEW_MNEMONICS || TARGET_64BIT) + abort (); + + fprintf (file, "\t.ualong 0,0\n"); /* offset 0 */ + fprintf (file, "\tmflr %s\n", r0); /* offset 8 */ + fprintf (file, "\tbl .LTRAMP1\n"); /* offset 12 */ + fprintf (file, "\t.ualong 0,0\n"); /* offset 16 */ + fprintf (file, ".LTRAMP1:\n"); + fprintf (file, "\tmflr %s\n", sc); /* offset 28 */ + fprintf (file, "\tmtlr %s\n", r0); /* offset 32 */ + fprintf (file, "\tlwz %s,0(%s)\n", r0, sc); /* offset 36 */ + fprintf (file, "\tlwz %s,4(%s)\n", sc, sc); /* offset 40 */ + fprintf (file, "\tmtctr %s\n", r0); /* offset 44 */ + fprintf (file, "\tbctr\n"); /* offset 48 */ + break; + } + + return; +} + +/* Length in units of the trampoline for entering a nested function. */ + +int +rs6000_trampoline_size () +{ + int ret = 0; + + switch (DEFAULT_ABI) + { + default: + abort (); + + case ABI_AIX: + ret = (TARGET_64BIT) ? 24 : 12; + break; + + case ABI_V4: + case ABI_AIX_NODESC: + ret = (TARGET_64BIT ? 48 : 40); + break; + + case ABI_NT: + ret = 52; + break; + } + + return ret; +} + +/* 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. */ + +void +rs6000_initialize_trampoline (addr, fnaddr, cxt) + rtx addr; + rtx fnaddr; + rtx cxt; +{ + rtx reg, reg2, reg3; + + switch (DEFAULT_ABI) + { + default: + abort (); + + /* Under AIX, just build the 3 word function descriptor */ + case ABI_AIX: + emit_move_insn (gen_rtx (MEM, SImode, + memory_address (SImode, (addr))), + gen_rtx (MEM, SImode, + memory_address (SImode, (fnaddr)))); + emit_move_insn (gen_rtx (MEM, SImode, + memory_address (SImode, + plus_constant ((addr), 4))), + gen_rtx (MEM, SImode, + memory_address (SImode, + plus_constant ((fnaddr), 4)))); + emit_move_insn (gen_rtx (MEM, SImode, + memory_address (SImode, + plus_constant ((addr), 8))), + force_reg (SImode, (cxt))); + break; + + /* Under V.4/eabi, update the two words after the bl to have the real + function address and the static chain. */ + case ABI_V4: + case ABI_AIX_NODESC: + reg = gen_reg_rtx (Pmode); + + emit_move_insn (reg, fnaddr); + emit_move_insn (gen_rtx (MEM, Pmode, plus_constant (addr, 8)), reg); + emit_move_insn (gen_rtx (MEM, Pmode, + plus_constant (addr, (TARGET_64BIT ? 16 : 12))), + cxt); + + rs6000_sync_trampoline (addr); + break; + + /* Under NT, update the first 2 words to look like a normal descriptor, and + then fill in the fields with the function address and static chain after + the bl instruction. */ + case ABI_NT: + reg = gen_reg_rtx (Pmode); + reg2 = gen_reg_rtx (Pmode); + reg3 = gen_reg_rtx (Pmode); + + emit_move_insn (gen_rtx (MEM, Pmode, plus_constant (addr, 4)), + gen_rtx (REG, Pmode, 2)); + emit_move_insn (reg, fnaddr); + emit_move_insn (reg2, gen_rtx (MEM, Pmode, reg)); + emit_move_insn (reg3, plus_constant (addr, 8)); + emit_move_insn (gen_rtx (MEM, Pmode, plus_constant (addr, 16)), reg); + emit_move_insn (gen_rtx (MEM, Pmode, addr), reg3); + emit_move_insn (gen_rtx (MEM, Pmode, plus_constant (addr, 20)), cxt); + rs6000_sync_trampoline (addr); + break; + } + + return; +} diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 7cb08fea37e..f52a3814ab6 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -63,8 +63,11 @@ Boston, MA 02111-1307, USA. */ %{mcpu=rsc1: -D_ARCH_PWR} \ %{mcpu=403: -D_ARCH_PPC} \ %{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \ +%{mcpu=602: -D_ARCH_PPC} \ %{mcpu=603: -D_ARCH_PPC} \ -%{mcpu=604: -D_ARCH_PPC}" +%{mcpu=603e: -D_ARCH_PPC} \ +%{mcpu=604: -D_ARCH_PPC} \ +%{mcpu=620: -D_ARCH_PPC}" /* Define the options for the binder: Start text at 512, align all segments to 512 bytes, and warn if there is text relocation. @@ -80,9 +83,15 @@ Boston, MA 02111-1307, USA. */ that to actually build a shared library you will also need to specify an export list with the -Wl,-bE option. */ +#ifndef CROSS_COMPILE +#define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\ + %{static:-bnso} \ + %{shared:-bM:SRE}" +#else #define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\ %{static:-bnso -bI:/lib/syscalls.exp} \ %{!shared:%{g*:-bexport:/usr/lib/libg.exp}} %{shared:-bM:SRE}" +#endif /* Profiled library versions are used by linking with special directories. */ #define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\ @@ -187,6 +196,25 @@ extern int target_flags; #define TARGET_TOC 1 #endif +/* Pseudo target to say whether this is Windows NT */ +#ifndef TARGET_WINDOWS_NT +#define TARGET_WINDOWS_NT 0 +#endif + +/* Pseudo target to say whether this is MAC */ +#ifndef TARGET_MACOS +#define TARGET_MACOS 0 +#endif + +/* Pseudo target to say whether this is AIX */ +#ifndef TARGET_AIX +#if (TARGET_ELF || TARGET_WINDOWS_NT || TARGET_MACOS) +#define TARGET_AIX 0 +#else +#define TARGET_AIX 1 +#endif +#endif + /* Run-time compilation parameters selecting different hardware subsets. Macro to define tables used to set the flags. @@ -246,6 +274,7 @@ enum processor_type PROCESSOR_RIOS2, PROCESSOR_PPC403, PROCESSOR_PPC601, + PROCESSOR_PPC602, PROCESSOR_PPC603, PROCESSOR_PPC604, PROCESSOR_PPC620}; @@ -256,7 +285,7 @@ extern enum processor_type rs6000_cpu; #define rs6000_cpu_attr ((enum attr_cpu)rs6000_cpu) /* Define generic processor types based upon current deployment. */ -#define PROCESSOR_COMMON PROCESSOR_PPC601 +#define PROCESSOR_COMMON PROCESSOR_PPC604 #define PROCESSOR_POWER PROCESSOR_RIOS1 #define PROCESSOR_POWERPC PROCESSOR_PPC601 @@ -284,8 +313,16 @@ extern enum processor_type rs6000_cpu; extern char *m88k_short_data; #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */ -#define TARGET_OPTIONS \ -{ {"cpu=", &rs6000_cpu_string}} +/* This is meant to be overriden in target specific files. */ +#ifndef SUBTARGET_OPTIONS +#define SUBTARGET_OPTIONS +#endif + +#define TARGET_OPTIONS \ +{ \ + {"cpu=", &rs6000_cpu_string} \ + SUBTARGET_OPTIONS \ +} extern char *rs6000_cpu_string; @@ -670,6 +707,9 @@ extern char *rs6000_cpu_string; /* Place to put static chain when calling a function that requires it. */ #define STATIC_CHAIN_REGNUM 11 +/* count register number for special purposes */ +#define COUNT_REGISTER_REGNUM 66 + /* Place that structure value return address is placed. On the RS/6000, it is passed as an extra parameter. */ @@ -802,12 +842,16 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS, /* Optional extra constraints for this machine. - For the RS/6000, `Q' means that this is a memory operand that is just - an offset from a register. */ + 'Q' means that is a memory operand that is just an offset from a reg. + 'R' is for AIX TOC entries. + 'S' is for Windows NT SYMBOL_REFs + 'T' is for Windows NT LABEL_REFs. */ #define EXTRA_CONSTRAINT(OP, C) \ ((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG \ : (C) == 'R' ? LEGITIMATE_CONSTANT_POOL_ADDRESS_P (OP) \ + : (C) == 'S' ? (TARGET_WINDOWS_NT && DEFAULT_ABI == ABI_NT && GET_CODE (OP) == SYMBOL_REF)\ + : (C) == 'T' ? (TARGET_WINDOWS_NT && DEFAULT_ABI == ABI_NT && GET_CODE (OP) == LABEL_REF) \ : 0) /* Given an rtx X being reloaded into a reg required to be @@ -857,32 +901,49 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS, enum rs6000_abi { ABI_NONE, ABI_AIX, /* IBM's AIX */ - ABI_V4 /* System V.4/eabi */ + ABI_AIX_NODESC, /* AIX calling sequence minus function descriptors */ + ABI_V4, /* System V.4/eabi */ + ABI_NT /* Windows/NT */ }; +extern enum rs6000_abi rs6000_current_abi; /* available for use by subtarget */ + +/* Default ABI to compile code for */ +#ifndef DEFAULT_ABI +#define DEFAULT_ABI ABI_AIX +#endif + /* Structure used to define the rs6000 stack */ typedef struct rs6000_stack { int first_gp_reg_save; /* first callee saved GP register used */ int first_fp_reg_save; /* first callee saved FP register used */ int lr_save_p; /* true if the link reg needs to be saved */ int cr_save_p; /* true if the CR reg needs to be saved */ + int toc_save_p; /* true if the TOC needs to be saved */ int push_p; /* true if we need to allocate stack space */ int calls_p; /* true if the function makes any calls */ + int main_p; /* true if this is main */ + int main_save_p; /* true if this is main and we need to save args */ enum rs6000_abi abi; /* which ABI to use */ int gp_save_offset; /* offset to save GP regs from initial SP */ int fp_save_offset; /* offset to save FP regs from initial SP */ int lr_save_offset; /* offset to save LR from initial SP */ int cr_save_offset; /* offset to save CR from initial SP */ + int toc_save_offset; /* offset to save the TOC pointer */ int varargs_save_offset; /* offset to save the varargs registers */ + int main_save_offset; /* offset to save main's args */ int reg_size; /* register size (4 or 8) */ int varargs_size; /* size to hold V.4 args passed in regs */ int vars_size; /* variable save area size */ int parm_size; /* outgoing parameter size */ + int main_size; /* size to hold saving main's args */ int save_size; /* save area size */ int fixed_size; /* fixed size of stack frame */ int gp_size; /* size of saved GP registers */ int fp_size; /* size of saved FP registers */ int cr_size; /* size to hold CR if not in save_size */ + int lr_size; /* size to hold LR if not in save_size */ + int toc_size; /* size to hold TOC if not in save_size */ int total_size; /* total bytes allocated for stack */ } rs6000_stack_t; @@ -905,6 +966,12 @@ typedef struct rs6000_stack { /* Size of the fixed area on the stack */ #define RS6000_SAVE_AREA (TARGET_64BIT ? 48 : 24) +/* Address to save the TOC register */ +#define RS6000_SAVE_TOC plus_constant (stack_pointer_rtx, 20) + +/* Whether a separate TOC save area is needed */ +extern int rs6000_save_toc_p; + /* Size of the V.4 varargs area if needed */ #define RS6000_VARARGS_AREA 0 @@ -1130,6 +1197,13 @@ typedef struct rs6000_args #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ function_arg_pass_by_reference(&CUM, MODE, TYPE, NAMED) +/* 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) \ + function_arg_boundary (MODE, TYPE) + /* Perform any needed actions needed for a function that is receiving a variable number of arguments. @@ -1202,40 +1276,19 @@ typedef struct rs6000_args of a trampoline, leaving space for the variable parts. The trampoline should set the static chain pointer to value placed - into the trampoline and should branch to the specified routine. - - On the RS/6000, this is not code at all, but merely a data area, - since that is the way all functions are called. The first word is - the address of the function, the second word is the TOC pointer (r2), - and the third word is the static chain value. */ - -#define TRAMPOLINE_TEMPLATE(FILE) { fprintf (FILE, "\t.long 0, 0, 0\n"); } + into the trampoline and should branch to the specified routine. */ +#define TRAMPOLINE_TEMPLATE(FILE) rs6000_trampoline_template (FILE) /* Length in units of the trampoline for entering a nested function. */ -#define TRAMPOLINE_SIZE 12 +#define TRAMPOLINE_SIZE rs6000_trampoline_size () /* Emit RTL insns to initialize the variable parts of a trampoline. FNADDR is an RTX for the address of the function's pure code. CXT is an RTX for the static chain value for the function. */ #define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, CXT) \ -{ \ - emit_move_insn (gen_rtx (MEM, SImode, \ - memory_address (SImode, (ADDR))), \ - gen_rtx (MEM, SImode, \ - memory_address (SImode, (FNADDR)))); \ - emit_move_insn (gen_rtx (MEM, SImode, \ - memory_address (SImode, \ - plus_constant ((ADDR), 4))), \ - gen_rtx (MEM, SImode, \ - memory_address (SImode, \ - plus_constant ((FNADDR), 4)))); \ - emit_move_insn (gen_rtx (MEM, SImode, \ - memory_address (SImode, \ - plus_constant ((ADDR), 8))), \ - force_reg (SImode, (CXT))); \ -} + rs6000_initialize_trampoline (ADDR, FNADDR, CXT) /* Definitions for __builtin_return_address and __builtin_frame_address. __builtin_return_address (0) should give link register (65), enable @@ -1247,13 +1300,15 @@ typedef struct rs6000_args (mrs) */ /* #define RETURN_ADDR_IN_PREVIOUS_FRAME */ -/* Number of bytes into the frame return addresses can be found. */ -#ifndef TARGET_V4_CALLS -#define RETURN_ADDRESS_OFFSET 8 -#else -#define RETURN_ADDRESS_OFFSET \ - ((TARGET_V4_CALLS) ? (TARGET_64BIT ? 8 : 4) : 8) -#endif +/* Number of bytes into the frame return addresses can be found. See + rs6000_stack_info in rs6000.c for more information on how the different + abi's store the return address. */ +#define RETURN_ADDRESS_OFFSET \ + ((DEFAULT_ABI == ABI_AIX \ + || DEFAULT_ABI == ABI_AIX_NODESC) ? 8 : \ + (DEFAULT_ABI == ABI_V4) ? (TARGET_64BIT ? 8 : 4) : \ + (DEFAULT_ABI == ABI_NT) ? -4 : \ + (fatal ("RETURN_ADDRESS_OFFSET not supported"), 0)) /* The current return address is in link register (65). The return address of anything farther back is accessed normally at an offset of 8 from the @@ -1638,8 +1693,13 @@ typedef struct rs6000_args .stabs in cc1plus. */ #define FASCIST_ASSEMBLER + +#ifndef ASM_OUTPUT_CONSTRUCTOR #define ASM_OUTPUT_CONSTRUCTOR(file, name) +#endif +#ifndef ASM_OUTPUT_DESTRUCTOR #define ASM_OUTPUT_DESTRUCTOR(file, name) +#endif /* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits is done just by pretending it is already truncated. */ @@ -2106,19 +2166,17 @@ toc_section () \ do \ { \ char *_name = (NAME); \ + int _len; \ if (_name[0] == '*') \ - (VAR) = _name+1; \ + _name++; \ + _len = strlen (_name); \ + if (_name[_len - 1] != ']') \ + (VAR) = _name; \ else \ { \ - int _len = strlen (_name); \ - if (_name[_len - 1] != ']') \ - (VAR) = _name; \ - else \ - { \ - (VAR) = (char *) alloca (_len + 1); \ - strcpy ((VAR), _name); \ - (VAR)[_len - 4] = '\0'; \ - } \ + (VAR) = (char *) alloca (_len + 1); \ + strcpy ((VAR), _name); \ + (VAR)[_len - 4] = '\0'; \ } \ } \ while (0) @@ -2468,6 +2526,7 @@ do { \ {"easy_fp_constant", {CONST_DOUBLE}}, \ {"reg_or_mem_operand", {SUBREG, MEM, REG}}, \ {"lwa_operand", {SUBREG, MEM, REG}}, \ + {"volatile_mem_operand", {MEM}}, \ {"offsettable_addr_operand", {REG, SUBREG, PLUS}}, \ {"fp_reg_or_mem_operand", {SUBREG, MEM, REG}}, \ {"mem_or_easy_const_operand", {SUBREG, MEM, CONST_DOUBLE}}, \ @@ -2478,6 +2537,7 @@ do { \ {"logical_operand", {SUBREG, REG, CONST_INT}}, \ {"non_logical_cint_operand", {CONST_INT}}, \ {"mask_operand", {CONST_INT}}, \ + {"count_register_operand", {REG}}, \ {"call_operand", {SYMBOL_REF, REG}}, \ {"current_file_function_operand", {SYMBOL_REF}}, \ {"input_operand", {SUBREG, MEM, REG, CONST_INT, SYMBOL_REF}}, \ @@ -2488,6 +2548,16 @@ do { \ {"scc_comparison_operator", {EQ, NE, LE, LT, GE, \ GT, LEU, LTU, GEU, GTU}}, + +/* uncomment for disabling the corresponding default options */ +/* #define MACHINE_no_sched_interblock */ +/* #define MACHINE_no_sched_speculative */ +/* #define MACHINE_no_sched_speculative_load */ + +/* indicate that issue rate is defined for this machine + (no need to use the default) */ +#define MACHINE_issue_rate + /* Declare functions in rs6000.c */ extern void output_options (); extern void rs6000_override_options (); @@ -2524,6 +2594,7 @@ extern int current_file_function_operand (); extern int input_operand (); extern void init_cumulative_args (); extern void function_arg_advance (); +extern int function_arg_boundary (); extern struct rtx_def *function_arg (); extern int function_arg_partial_nregs (); extern int function_arg_pass_by_reference (); @@ -2555,3 +2626,6 @@ extern void output_ascii (); extern void rs6000_gen_section_name (); extern void output_function_profiler (); extern int rs6000_adjust_cost (); +extern void rs6000_trampoline_template (); +extern int rs6000_trampoline_size (); +extern void rs6000_initialize_trampoline (); diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 3a975abe03f..3a46ecc915e 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -40,7 +40,7 @@ ;; Processor type -- this attribute must exactly match the processor_type ;; enumeration in rs6000.h. -(define_attr "cpu" "rios1,rios2,ppc403,ppc601,ppc603,ppc604,ppc620" +(define_attr "cpu" "rios1,rios2,ppc403,ppc601,ppc602,ppc603,ppc604,ppc620" (const (symbol_ref "rs6000_cpu_attr"))) ; (define_function_unit NAME MULTIPLICITY SIMULTANEITY @@ -50,39 +50,44 @@ ; (POWER and 601 use Integer Unit) (define_function_unit "lsu" 1 0 (and (eq_attr "type" "load") - (eq_attr "cpu" "rios2,ppc603,ppc604,ppc620")) - 2 0) + (eq_attr "cpu" "ppc602,ppc603,ppc604,ppc620")) + 2 1) (define_function_unit "lsu" 1 0 (and (eq_attr "type" "fpload") - (eq_attr "cpu" "rios2,ppc603,ppc604,ppc620")) - 2 0) + (eq_attr "cpu" "ppc604,ppc620")) + 3 1) + +(define_function_unit "lsu" 1 0 + (and (eq_attr "type" "fpload") + (eq_attr "cpu" "ppc602,ppc603")) + 2 1) (define_function_unit "iu" 1 0 (and (eq_attr "type" "load") - (eq_attr "cpu" "rios1,ppc403,ppc601")) - 2 0) + (eq_attr "cpu" "rios1,ppc601")) + 2 1) (define_function_unit "iu" 1 0 (and (eq_attr "type" "fpload") (eq_attr "cpu" "rios1,ppc601")) - 3 0) + 2 0) ; Integer Unit (RIOS1, PPC601, PPC603) ; Trivial operations take one cycle which need not be listed here. (define_function_unit "iu" 1 0 - (and (eq_attr "type" "imul") - (eq_attr "cpu" "rios1")) - 3 3) + (and (eq_attr "type" "integer") + (eq_attr "cpu" "rios1,ppc601")) + 1 1) (define_function_unit "iu" 1 0 (and (eq_attr "type" "imul") - (eq_attr "cpu" "ppc403")) - 4 4) + (eq_attr "cpu" "rios1")) + 3 3) (define_function_unit "iu" 1 0 (and (eq_attr "type" "imul") - (eq_attr "cpu" "ppc601,ppc603")) + (eq_attr "cpu" "ppc601,ppc602,ppc603")) 5 5) (define_function_unit "iu" 1 0 @@ -90,11 +95,6 @@ (eq_attr "cpu" "rios1")) 19 19) -(define_function_unit "iu" 1 0 - (and (eq_attr "type" "idiv") - (eq_attr "cpu" "ppc403")) - 33 33) - (define_function_unit "iu" 1 0 (and (eq_attr "type" "idiv") (eq_attr "cpu" "ppc601")) @@ -102,35 +102,47 @@ (define_function_unit "iu" 1 0 (and (eq_attr "type" "idiv") - (eq_attr "cpu" "ppc603")) + (eq_attr "cpu" "ppc602,ppc603")) 37 36) ; RIOS2 has two integer units: a primary one which can perform all ; operations and a secondary one which is fed in lock step with the first -; and can perform "simple" integer operations. +; and can perform "simple" integer operations. +; To catch this we define a 'dummy' imuldiv-unit that is also needed +; for the complex insns. (define_function_unit "iu2" 2 0 (and (eq_attr "type" "integer") (eq_attr "cpu" "rios2")) - 1 0 - [(eq_attr "type" "imul,idiv")]) + 1 0) + +(define_function_unit "iu2" 2 0 + (and (eq_attr "type" "imul") + (eq_attr "cpu" "rios2")) + 2 2) + +(define_function_unit "iu2" 2 0 + (and (eq_attr "type" "idiv") + (eq_attr "cpu" "rios2")) + 13 13) (define_function_unit "imuldiv" 1 0 (and (eq_attr "type" "imul") (eq_attr "cpu" "rios2")) - 2 2 - [(eq_attr "type" "integer")]) + 2 2) + (define_function_unit "imuldiv" 1 0 (and (eq_attr "type" "idiv") (eq_attr "cpu" "rios2")) - 13 13 - [(eq_attr "type" "integer")]) + 13 13) -; PPC604 has three integer units: one primary and two secondary. -(define_function_unit "iu3" 3 0 +; PPC604 has two units that perform integer operations +; and one unit for divide/multiply operations (and move +; from/to spr). +(define_function_unit "iu2" 2 0 (and (eq_attr "type" "integer") (eq_attr "cpu" "ppc604,ppc620")) - 1 0 + 1 1 [(eq_attr "type" "imul,idiv")]) (define_function_unit "imuldiv" 1 0 @@ -145,24 +157,65 @@ 20 19 [(eq_attr "type" "integer")]) -; Branch Processing Unit -(define_function_unit "bpu" 1 0 - (eq_attr "type" "compare") - 4 0) +; compare is done on integer unit, but feeds insns which +; execute on the branch unit. Ready-delay of the compare +; on the branch unit is large (3-5 cycles). On the iu/fpu +; it is 1. One drawback is that the compare will also be +; assigned to the bpu, but this inaccuracy is worth for being +; able to fill the compare-branch delay, with insns on iu/fpu. +(define_function_unit "iu" 1 0 + (and (eq_attr "type" "compare") + (eq_attr "cpu" "rios1,ppc601")) + 1 1) + +(define_function_unit "iu2" 2 0 + (and (eq_attr "type" "compare") + (eq_attr "cpu" "rios2")) + 1 1) + +(define_function_unit "bpu" 1 0 + (and (eq_attr "type" "compare") + (eq_attr "cpu" "rios1,rios2,ppc601")) + 4 1) + +; different machines have different compare timings +; in ppc604, compare is done on the one of the two +; main integer units. +(define_function_unit "iu2" 2 0 + (and (eq_attr "type" "compare") + (eq_attr "cpu" "ppc604,ppc620")) + 1 1) (define_function_unit "bpu" 1 0 (eq_attr "type" "delayed_compare") 5 0) -(define_function_unit "bpu" 1 0 +; fp compare uses fp unit +(define_function_unit "fpu" 1 0 (and (eq_attr "type" "fpcompare") - (eq_attr "cpu" "rios1,rios2")) - 8 0) + (eq_attr "cpu" "rios1")) + 8 1) -(define_function_unit "bpu" 1 0 +; rios1 and rios2 have different fpcompare delays +(define_function_unit "fpu2" 2 0 (and (eq_attr "type" "fpcompare") - (eq_attr "cpu" "ppc601,ppc603,ppc604,ppc620")) - 4 0) + (eq_attr "cpu" "rios2")) + 5 1) + +; on ppc601 and ppc603, fpcompare takes also 2 cycles from +; the integer unit +; here we do not define delays, just occupy the unit. The dependencies +; will be signed by the fpcompare definition in the fpu. +(define_function_unit "iu" 1 0 + (and (eq_attr "type" "fpcompare") + (eq_attr "cpu" "ppc601,ppc602,ppc603")) + 0 2) + +; fp compare uses fp unit +(define_function_unit "fpu" 1 0 + (and (eq_attr "type" "fpcompare") + (eq_attr "cpu" "ppc601,ppc602,ppc603,ppc604,ppc620")) + 5 1) (define_function_unit "bpu" 1 0 (and (eq_attr "type" "mtjmpr") @@ -171,9 +224,18 @@ (define_function_unit "bpu" 1 0 (and (eq_attr "type" "mtjmpr") - (eq_attr "cpu" "ppc403,ppc601,ppc603,ppc604,ppc620")) + (eq_attr "cpu" "ppc601,ppc602,ppc603,ppc604,ppc620")) 4 0) +; all jumps/branches are executing on the bpu, in 1 cycle, for all machines. +(define_function_unit "bpu" 1 0 + (eq_attr "type" "jmpreg") + 1 0) + +(define_function_unit "bpu" 1 0 + (eq_attr "type" "branch") + 1 0) + ; Floating Point Unit (RIOS1, PPC601, PPC603, PPC604). (define_function_unit "fpu" 1 0 (and (eq_attr "type" "fp,dmul") @@ -187,23 +249,24 @@ (define_function_unit "fpu" 1 0 (and (eq_attr "type" "fp") - (eq_attr "cpu" "ppc603,ppc604,ppc620")) - 3 0) + (eq_attr "cpu" "ppc602,ppc603,ppc604,ppc620")) + 3 1) (define_function_unit "fpu" 1 0 (and (eq_attr "type" "dmul") (eq_attr "cpu" "ppc601")) - 5 5) + 5 2) +; is this true? (define_function_unit "fpu" 1 0 (and (eq_attr "type" "dmul") - (eq_attr "cpu" "ppc603")) + (eq_attr "cpu" "ppc602,ppc603")) 4 2) (define_function_unit "fpu" 1 0 (and (eq_attr "type" "dmul") (eq_attr "cpu" "ppc604,ppc620")) - 3 0) + 3 1) (define_function_unit "fpu" 1 0 (and (eq_attr "type" "sdiv,ddiv") @@ -217,7 +280,7 @@ (define_function_unit "fpu" 1 0 (and (eq_attr "type" "sdiv") - (eq_attr "cpu" "ppc603,ppc604,ppc620")) + (eq_attr "cpu" "ppc602,ppc603,ppc604,ppc620")) 18 18) (define_function_unit "fpu" 1 0 @@ -227,7 +290,7 @@ (define_function_unit "fpu" 1 0 (and (eq_attr "type" "ddiv") - (eq_attr "cpu" "ppc603")) + (eq_attr "cpu" "ppc602,ppc603")) 33 33) (define_function_unit "fpu" 1 0 @@ -260,6 +323,7 @@ (and (eq_attr "type" "ssqrt,dsqrt") (eq_attr "cpu" "rios2")) 26 26) + ;; Start with fixed-point load and store insns. Here we put only the more ;; complex forms. Basic data transfer is done later. @@ -1284,12 +1348,11 @@ if (GET_CODE (operands[2]) == CONST_INT && exact_log2 (INTVAL (operands[2])) >= 0) ; - else if (TARGET_POWER && ! TARGET_POWERPC) + else if (TARGET_POWERPC) + operands[2] = force_reg (SImode, operands[2]); + else if (TARGET_POWER) FAIL; else - operands[2] = force_reg (SImode, operands[2]); - - if (! TARGET_POWER && ! TARGET_POWERPC) { emit_move_insn (gen_rtx (REG, SImode, 3), operands[1]); emit_move_insn (gen_rtx (REG, SImode, 4), operands[2]); @@ -3898,12 +3961,61 @@ rtx target = (reload_completed || reload_in_progress) ? operands[0] : gen_reg_rtx (SImode); + /* If this is a function address on -mcall-aixdesc or -mcall-nt, + convert it to the address of the descriptor. */ + if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT) + && GET_CODE (operands[1]) == SYMBOL_REF + && XSTR (operands[1], 0)[0] == '.') + { + char *name = XSTR (operands[1], 0); + rtx new_ref; + while (*name == '.') + name++; + new_ref = gen_rtx (SYMBOL_REF, Pmode, name); + CONSTANT_POOL_ADDRESS_P (new_ref) = CONSTANT_POOL_ADDRESS_P (operands[1]); + SYMBOL_REF_FLAG (new_ref) = SYMBOL_REF_FLAG (operands[1]); + SYMBOL_REF_USED (new_ref) = SYMBOL_REF_USED (operands[1]); + operands[1] = new_ref; + } + emit_insn (gen_elf_high (target, operands[1])); emit_insn (gen_elf_low (operands[0], target, operands[1])); DONE; } - if (CONSTANT_P (operands[1]) + if (GET_CODE (operands[1]) == CONST + && DEFAULT_ABI == ABI_NT + && !side_effects_p (operands[0])) + { + rtx const_term = const0_rtx; + rtx sym = eliminate_constant_term (XEXP (operands[1], 0), &const_term); + if (sym && GET_CODE (const_term) == CONST_INT + && (GET_CODE (sym) == SYMBOL_REF || GET_CODE (sym) == LABEL_REF)) + { + emit_insn (gen_movsi (operands[0], sym)); + if (INTVAL (const_term) != 0) + { + unsigned HOST_WIDE_INT value = INTVAL (const_term); + if (value + 0x8000 < 0x10000) + emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (value))); + else + { + emit_insn (gen_addsi3 (operands[0], operands[0], + GEN_INT ((value >> 16) + ((value >> 15) & 1)))); + + if ((value & 0xffff) != 0) + emit_insn (gen_addsi3 (operands[0], operands[0], + GEN_INT (value & 0xffff))); + } + } + DONE; + } + else + fatal_insn (\"bad address\", operands[1]); + } + + if ((!TARGET_WINDOWS_NT || DEFAULT_ABI != ABI_NT) + && CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != CONST_INT && GET_CODE (operands[1]) != HIGH && ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])) @@ -3949,12 +4061,14 @@ }") (define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*q,*c*l,*h") - (match_operand:SI 1 "input_operand" "r,m,r,I,J,R,*h,r,r,0"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m,r,r,r,r,*q,*c*l,*h") + (match_operand:SI 1 "input_operand" "r,S,T,m,r,I,J,R,*h,r,r,0"))] "gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode)" "@ mr %0,%1 + {l|lwz} %0,[toc]%1(2) + {l|lwz} %0,[toc]%l1(2) {l%U1%X1|lwz%U1%X1} %0,%1 {st%U0%X0|stw%U0%X0} %1,%0 {lil|li} %0,%1 @@ -3964,7 +4078,7 @@ mt%0 %1 mt%0 %1 cror 0,0,0" - [(set_attr "type" "*,load,*,*,*,*,*,*,mtjmpr,*")]) + [(set_attr "type" "*,load,load,load,*,*,*,*,*,*,mtjmpr,*")]) ;; Split a load of a large constant into the appropriate two-insn ;; sequence. @@ -4823,10 +4937,10 @@ ;; Argument 3 is the alignment (define_expand "movstrsi" - [(parallel [(set (match_operand:BLK 0 "memory_operand" "") - (match_operand:BLK 1 "memory_operand" "")) - (use (match_operand:SI 2 "general_operand" "")) - (use (match_operand:SI 3 "immediate_operand" ""))])] + [(parallel [(set (match_operand:BLK 0 "" "") + (match_operand:BLK 1 "" "")) + (use (match_operand:SI 2 "" "")) + (use (match_operand:SI 3 "" ""))])] "" " { @@ -4839,10 +4953,10 @@ ;; Move up to 32 bytes at a time. The fixed registers are needed because the ;; register allocator doesn't have a clue about allocating 8 word registers (define_expand "movstrsi_8reg" - [(parallel [(set (mem:BLK (match_operand:SI 0 "register_operand" "")) - (mem:BLK (match_operand:SI 1 "register_operand" ""))) - (use (match_operand:SI 2 "immediate_operand" "")) - (use (match_operand:SI 3 "immediate_operand" "")) + [(parallel [(set (match_operand 0 "" "") + (match_operand 1 "" "")) + (use (match_operand 2 "" "")) + (use (match_operand 3 "" "")) (clobber (reg:SI 5)) (clobber (reg:SI 6)) (clobber (reg:SI 7)) @@ -4902,10 +5016,10 @@ ;; Move up to 24 bytes at a time. The fixed registers are needed because the ;; register allocator doesn't have a clue about allocating 6 word registers (define_expand "movstrsi_6reg" - [(parallel [(set (mem:BLK (match_operand:SI 0 "register_operand" "")) - (mem:BLK (match_operand:SI 1 "register_operand" ""))) - (use (match_operand:SI 2 "immediate_operand" "")) - (use (match_operand:SI 3 "immediate_operand" "")) + [(parallel [(set (match_operand 0 "" "") + (match_operand 1 "" "")) + (use (match_operand 2 "" "")) + (use (match_operand 3 "" "")) (clobber (reg:SI 7)) (clobber (reg:SI 8)) (clobber (reg:SI 9)) @@ -4959,10 +5073,10 @@ ;; Move up to 16 bytes at a time, using 4 fixed registers to avoid spill problems ;; with TImode (define_expand "movstrsi_4reg" - [(parallel [(set (mem:BLK (match_operand:SI 0 "register_operand" "")) - (mem:BLK (match_operand:SI 1 "register_operand" ""))) - (use (match_operand:SI 2 "immediate_operand" "")) - (use (match_operand:SI 3 "immediate_operand" "")) + [(parallel [(set (match_operand 0 "" "") + (match_operand 1 "" "")) + (use (match_operand 2 "" "")) + (use (match_operand 3 "" "")) (clobber (reg:SI 9)) (clobber (reg:SI 10)) (clobber (reg:SI 11)) @@ -5009,10 +5123,10 @@ ;; Move up to 8 bytes at a time. (define_expand "movstrsi_2reg" - [(parallel [(set (mem:BLK (match_operand:SI 0 "register_operand" "")) - (mem:BLK (match_operand:SI 1 "register_operand" ""))) - (use (match_operand:SI 2 "immediate_operand" "")) - (use (match_operand:SI 3 "immediate_operand" "")) + [(parallel [(set (match_operand 0 "" "") + (match_operand 1 "" "")) + (use (match_operand 2 "" "")) + (use (match_operand 3 "" "")) (clobber (match_scratch:DI 4 "")) (clobber (match_scratch:SI 5 ""))])] "TARGET_STRING && !TARGET_64BIT" @@ -5044,10 +5158,10 @@ ;; Move up to 4 bytes at a time. (define_expand "movstrsi_1reg" - [(parallel [(set (mem:BLK (match_operand:SI 0 "register_operand" "")) - (mem:BLK (match_operand:SI 1 "register_operand" ""))) - (use (match_operand:SI 2 "immediate_operand" "")) - (use (match_operand:SI 3 "immediate_operand" "")) + [(parallel [(set (match_operand 0 "" "") + (match_operand 1 "" "")) + (use (match_operand 2 "" "")) + (use (match_operand 3 "" "")) (clobber (match_scratch:SI 4 "")) (clobber (match_scratch:SI 5 ""))])] "TARGET_STRING" @@ -5395,32 +5509,132 @@ DONE; }") -;; A function pointer is a pointer to a data area whose first word contains -;; the actual address of the function, whose second word contains a pointer -;; to its TOC, and whose third word contains a value to place in the static -;; chain register (r11). Note that if we load the static chain, our + +;; A function pointer under AIX is a pointer to a data area whose first word +;; contains the actual address of the function, whose second word contains a +;; pointer to its TOC, and whose third word contains a value to place in the +;; static chain register (r11). Note that if we load the static chain, our ;; "trampoline" need not have any executable code. ;; -;; operands[0] is an SImode pseudo in which we place the address of the -;; function. -;; operands[1] is the address of data area of the function to call +;; operands[0] is a register pointing to the 3 word descriptor (aka, the function address) +;; operands[1] is the stack size to clean up +;; operands[2] is the value FUNCTION_ARG returns for the VOID argument (must be 0 for AIX) +;; operands[3] is location to store the TOC +;; operands[4] is the TOC register +;; operands[5] is the static chain register +;; +;; We do not break this into separate insns, so that the scheduler will not try +;; to move the load of the new TOC before any loads from the TOC. + +(define_insn "call_indirect_aix" + [(call (mem:SI (match_operand:SI 0 "register_operand" "b")) + (match_operand 1 "const_int_operand" "n")) + (use (match_operand 2 "const_int_operand" "O")) + (use (match_operand 3 "offsettable_addr_operand" "p")) + (use (match_operand 4 "register_operand" "r")) + (clobber (match_operand 5 "register_operand" "=r")) + (clobber (match_scratch:SI 6 "=&r")) + (clobber (match_scratch:SI 7 "=l"))] + "DEFAULT_ABI == ABI_AIX" + "{st|stw} %4,%a3\;{l|lwz} %6,0(%0)\;{l|lwz} %4,4(%0);\;mt%7 %6\;{l|lwz} %5,8(%0)\;{brl|blrl}\;{l|lwz} %4,%a3" + [(set_attr "length" "28")]) + +(define_insn "call_value_indirect_aix" + [(set (match_operand 0 "register_operand" "fg") + (call (mem:SI (match_operand:SI 1 "register_operand" "b")) + (match_operand 2 "const_int_operand" "n"))) + (use (match_operand 3 "const_int_operand" "O")) + (use (match_operand 4 "offsettable_addr_operand" "p")) + (use (match_operand 5 "register_operand" "r")) + (clobber (match_operand 6 "register_operand" "=r")) + (clobber (match_scratch:SI 7 "=&r")) + (clobber (match_scratch:SI 8 "=l"))] + "DEFAULT_ABI == ABI_AIX" + "{st|stw} %5,%a4\;{l|lwz} %7,0(%1)\;{l|lwz} %5,4(%1);\;mt%8 %7\;{l|lwz} %6,8(%1)\;{brl|blrl}\;{l|lwz} %5,%a4" + [(set_attr "length" "28")]) + +;; A function pointer undef NT is a pointer to a data area whose first word +;; contains the actual address of the function, whose second word contains a +;; pointer to its TOC. The static chain is not stored under NT, which means +;; that we need a trampoline. +;; +;; operands[0] is an SImode pseudo in which we place the address of the function. +;; operands[1] is the stack size to clean up +;; operands[2] is the value FUNCTION_ARG returns for the VOID argument (must be 0 for NT) +;; operands[3] is location to store the TOC +;; operands[4] is the TOC register +;; +;; We do not break this into separate insns, so that the scheduler will not try +;; to move the load of the new TOC before any loads from the TOC. + +(define_insn "call_indirect_nt" + [(call (mem:SI (match_operand:SI 0 "register_operand" "b")) + (match_operand 1 "const_int_operand" "n")) + (use (match_operand 2 "const_int_operand" "O")) + (use (match_operand 3 "offsettable_addr_operand" "p")) + (use (match_operand 4 "register_operand" "r")) + (clobber (match_scratch:SI 5 "=&r")) + (clobber (match_scratch:SI 6 "=l"))] + "DEFAULT_ABI == ABI_NT" + "{st|stw} %4,%a3\;{l|lwz} %6,0(%0)\;{l|lwz} %4,4(%0);\;mt%6 %5\;{brl|blrl}\;{l|lwz} %4,%a3" + [(set_attr "length" "24")]) + +(define_insn "call_value_indirect_nt" + [(set (match_operand 0 "register_operand" "fg") + (call (mem:SI (match_operand:SI 1 "register_operand" "b")) + (match_operand 2 "const_int_operand" "n"))) + (use (match_operand 3 "const_int_operand" "O")) + (use (match_operand 4 "offsettable_addr_operand" "p")) + (use (match_operand 5 "register_operand" "r")) + (clobber (match_scratch:SI 6 "=&r")) + (clobber (match_scratch:SI 7 "=l"))] + "DEFAULT_ABI == ABI_NT" + "{st|stw} %5,%a4\;{l|lwz} %6,0(%1)\;{l|lwz} %5,4(%1);\;mt%7 %6\;{brl|blrl}\;{l|lwz} %5,%a4" + [(set_attr "length" "24")]) + +;; A function pointer under System V is just a normal pointer +;; operands[0] is the function pointer +;; operands[1] is the stack size to clean up +;; operands[2] is the value FUNCTION_ARG returns for the VOID argument which indicates how to set cr1 + +(define_insn "call_indirect_sysv" + [(call (mem:SI (match_operand:SI 0 "register_operand" "l,l")) + (match_operand 1 "const_int_operand" "n,n")) + (use (match_operand 2 "const_int_operand" "O,n")) + (clobber (match_scratch:SI 3 "=l,l"))] + "DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC" + "* +{ + if (INTVAL (operands[2]) > 0) + return \"creqv 6,6,6\;{brl|blrl}\"; -(define_expand "call_via_ptr" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (mem:SI (match_operand:SI 1 "gpc_reg_operand" ""))) - (set (mem:SI (plus:SI (reg:SI 1) (const_int 20))) - (reg:SI 2)) - (set (reg:SI 2) - (mem:SI (plus:SI (match_dup 1) - (const_int 4)))) - (set (reg:SI 11) - (mem:SI (plus:SI (match_dup 1) - (const_int 8)))) - (use (reg:SI 2)) - (use (reg:SI 11))] - "" - "") + else if (INTVAL (operands[2]) < 0) + return \"crxor 6,6,6\;{brl|blrl}\"; + + return \"{brl|blrl}\"; +}" + [(set_attr "length" "4,8")]) + +(define_insn "call_value_indirect_sysv" + [(set (match_operand 0 "register_operand" "=fg,fg") + (call (mem:SI (match_operand:SI 1 "register_operand" "l,l")) + (match_operand 2 "const_int_operand" "n,n"))) + (use (match_operand 3 "const_int_operand" "O,n")) + (clobber (match_scratch:SI 4 "=l,l"))] + "DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC" + "* +{ + if (INTVAL (operands[3]) > 0) + return \"creqv 6,6,6\;{brl|blrl}\"; + + else if (INTVAL (operands[3]) < 0) + return \"crxor 6,6,6\;{brl|blrl}\"; + + return \"{brl|blrl}\"; +}" + [(set_attr "length" "4,8")]) +;; Now the definitions for the call and call_value insns (define_expand "call" [(parallel [(call (mem:SI (match_operand:SI 0 "address_operand" "")) (match_operand 1 "" "")) @@ -5435,13 +5649,33 @@ operands[0] = XEXP (operands[0], 0); if (GET_CODE (operands[0]) != SYMBOL_REF) { -#ifndef USING_SVR4_H - /* AIX function pointers are really pointers to a three word area */ - rtx temp = gen_reg_rtx (SImode); + if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC) + emit_call_insn (gen_call_indirect_sysv (force_reg (Pmode, operands[0]), + operands[1], operands[2])); + else + { + rtx toc_reg = gen_rtx (REG, Pmode, 2); + rtx toc_addr = RS6000_SAVE_TOC; - emit_insn (gen_call_via_ptr (temp, force_reg (SImode, operands[0]))); - operands[0] = temp; -#endif /* !USING_SVR4_H */ + if (DEFAULT_ABI == ABI_AIX) + { + /* AIX function pointers are really pointers to a three word area */ + rtx static_chain = gen_rtx (REG, Pmode, STATIC_CHAIN_REGNUM); + emit_call_insn (gen_call_indirect_aix (force_reg (Pmode, operands[0]), + operands[1], operands[2], + toc_addr, toc_reg, static_chain)); + } + else if (DEFAULT_ABI == ABI_NT) + { + /* NT function pointers are really pointers to a two word area */ + emit_call_insn (gen_call_indirect_nt (force_reg (Pmode, operands[0]), + operands[1], operands[2], + toc_addr, toc_reg)); + } + else + abort (); + } + DONE; } }") @@ -5460,13 +5694,35 @@ operands[1] = XEXP (operands[1], 0); if (GET_CODE (operands[1]) != SYMBOL_REF) { -#ifndef USING_SVR4_H - /* AIX function pointers are really pointers to a three word area */ - rtx temp = gen_reg_rtx (SImode); + if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC) + emit_call_insn (gen_call_value_indirect_sysv (operands[0], operands[1], + operands[2], operands[3])); + else + { + rtx toc_reg = gen_rtx (REG, Pmode, 2); + rtx toc_addr = RS6000_SAVE_TOC; - emit_insn (gen_call_via_ptr (temp, force_reg (SImode, operands[1]))); - operands[1] = temp; -#endif /* !USING_SVR4_H */ + if (DEFAULT_ABI == ABI_AIX) + { + /* AIX function pointers are really pointers to a three word area */ + rtx static_chain = gen_rtx (REG, Pmode, STATIC_CHAIN_REGNUM); + emit_call_insn (gen_call_value_indirect_aix (operands[0], + force_reg (Pmode, operands[1]), + operands[2], operands[3], + toc_addr, toc_reg, static_chain)); + } + else if (DEFAULT_ABI == ABI_NT) + { + /* NT function pointers are really pointers to a two word area */ + emit_call_insn (gen_call_value_indirect_nt (operands[0], + force_reg (Pmode, operands[1]), + operands[2], operands[3], + toc_addr, toc_reg)); + } + else + abort (); + } + DONE; } }") @@ -5502,11 +5758,11 @@ ;; and < 0 if they were not. (define_insn "" - [(call (mem:SI (match_operand:SI 0 "call_operand" "l,s,l,s")) - (match_operand 1 "" "fg,fg,fg,fg")) - (use (match_operand:SI 2 "immediate_operand" "O,O,n,n")) - (clobber (match_scratch:SI 3 "=l,l,l,l"))] - "" + [(call (mem:SI (match_operand:SI 0 "call_operand" "s,s")) + (match_operand 1 "" "fg,fg")) + (use (match_operand:SI 2 "immediate_operand" "O,n")) + (clobber (match_scratch:SI 3 "=l,l"))] + "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT" "* { if (INTVAL (operands[2]) > 0) @@ -5515,20 +5771,35 @@ else if (INTVAL (operands[2]) < 0) output_asm_insn (\"crxor 6,6,6\", operands); -#ifndef USING_SVR4_H + /* Indirect calls should go through call_indirect */ if (GET_CODE (operands[0]) == REG) - return \"{brl|blrl}\;{l|lwz} 2,20(1)\"; + abort (); - return \"bl %z0\;%.\"; + return (TARGET_WINDOWS_NT) ? \"bl %z0\;.znop %z0\" : \"bl %z0\;%.\"; +}" + [(set_attr "length" "8,12")]) -#else +(define_insn "" + [(call (mem:SI (match_operand:SI 0 "call_operand" "s,s")) + (match_operand 1 "" "fg,fg")) + (use (match_operand:SI 2 "immediate_operand" "O,n")) + (clobber (match_scratch:SI 3 "=l,l"))] + "DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_V4" + "* +{ + if (INTVAL (operands[2]) > 0) + output_asm_insn (\"creqv 6,6,6\", operands); + + else if (INTVAL (operands[2]) < 0) + output_asm_insn (\"crxor 6,6,6\", operands); + + /* Indirect calls should go through call_indirect */ if (GET_CODE (operands[0]) == REG) - return \"{brl|blrl}\"; + abort (); return \"bl %z0\"; -#endif }" - [(set_attr "length" "8,8,12,12")]) + [(set_attr "length" "4,8")]) (define_insn "" [(set (match_operand 0 "" "=fg,fg") @@ -5550,12 +5821,12 @@ [(set_attr "length" "4,8")]) (define_insn "" - [(set (match_operand 0 "" "=fg,fg,fg,fg") - (call (mem:SI (match_operand:SI 1 "call_operand" "l,s,l,s")) - (match_operand 2 "" "fg,fg,fg,fg"))) - (use (match_operand:SI 3 "immediate_operand" "O,O,n,n")) - (clobber (match_scratch:SI 4 "=l,l,l,l"))] - "" + [(set (match_operand 0 "" "=fg,fg") + (call (mem:SI (match_operand:SI 1 "call_operand" "s,s")) + (match_operand 2 "" "fg,fg"))) + (use (match_operand:SI 3 "immediate_operand" "O,n")) + (clobber (match_scratch:SI 4 "=l,l"))] + "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT" "* { if (INTVAL (operands[3]) > 0) @@ -5564,20 +5835,37 @@ else if (INTVAL (operands[3]) < 0) output_asm_insn (\"crxor 6,6,6\", operands); -#ifndef USING_SVR4_H + /* This should be handled by call_value_indirect */ if (GET_CODE (operands[1]) == REG) - return \"{brl|blrl}\;{l|lwz} 2,20(1)\"; + abort (); + + return (TARGET_WINDOWS_NT) ? \"bl %z1\;.znop %z1\" : \"bl %z1\;%.\"; +}" + [(set_attr "length" "8,12")]) + +(define_insn "" + [(set (match_operand 0 "" "=fg,fg") + (call (mem:SI (match_operand:SI 1 "call_operand" "s,s")) + (match_operand 2 "" "fg,fg"))) + (use (match_operand:SI 3 "immediate_operand" "O,n")) + (clobber (match_scratch:SI 4 "=l,l"))] + "DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_V4" + "* +{ + if (INTVAL (operands[3]) > 0) + output_asm_insn (\"creqv 6,6,6\", operands); - return \"bl %z1\;%.\"; + else if (INTVAL (operands[3]) < 0) + output_asm_insn (\"crxor 6,6,6\", operands); -#else + /* This should be handled by call_value_indirect */ if (GET_CODE (operands[1]) == REG) - return \"{brl|blrl}\"; + abort (); return \"bl %z1\"; -#endif }" - [(set_attr "length" "8,8,12,12")]) + [(set_attr "length" "4,8")]) + ;; Call subroutine returning any type. @@ -5616,12 +5904,32 @@ "" "") -;; Synchronize instruction/data caches for V.4 trampolines -(define_insn "sync_isync" - [(unspec [(match_operand 0 "memory_operand" "=m")] 1)] +;; Synchronize instructions/data caches for V.4 trampolines +;; The extra memory_operand is to prevent the optimizer from +;; deleting insns with "no" effect. +(define_insn "icbi" + [(unspec [(match_operand 0 "memory_operand" "=m") + (match_operand 1 "register_operand" "b") + (match_operand 2 "register_operand" "r")] 3)] + "TARGET_POWERPC" + "icbi %1,%2") + +(define_insn "dcbst" + [(unspec [(match_operand 0 "memory_operand" "=m") + (match_operand 1 "register_operand" "b") + (match_operand 2 "register_operand" "r")] 4)] + "TARGET_POWERPC" + "dcbst %1,%2") + +(define_insn "sync" + [(unspec [(match_operand 0 "memory_operand" "=m")] 5)] "" - "{dcs|sync}\;{ics|isync}" - [(set_attr "length" "8")]) + "{dcs|sync}") + +(define_insn "isync" + [(unspec [(match_operand 0 "memory_operand" "=m")] 6)] + "" + "{ics|isync}") ;; Compare insns are next. Note that the RS/6000 has two types of compares, @@ -7285,14 +7593,14 @@ ;; Define the subtract-one-and-jump insns, starting with the template ;; so loop.c knows what to generate. -(define_expand "decrement_and_branchsi" - [(parallel [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_dup 0) - (const_int -1))) - (set (pc) (if_then_else (ne (match_dup 0) +(define_expand "decrement_and_branch_on_count" + [(parallel [(set (pc) (if_then_else (ne (match_operand:SI 0 "register_operand" "") (const_int 1)) (label_ref (match_operand 1 "" "")) (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1))) (clobber (match_scratch:CC 2 "")) (clobber (match_scratch:SI 3 ""))])] "" @@ -7503,3 +7811,4 @@ " { operands[7] = gen_rtx (GET_CODE (operands[2]), VOIDmode, operands[3], const0_rtx); }") + diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index 1c54c6fc5a6..d7e8af0acbf 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -25,30 +25,38 @@ Boston, MA 02111-1307, USA. */ #define MASK_NO_BITFIELD_TYPE 0x40000000 /* Set PCC_BITFIELD_TYPE_MATTERS to 0 */ #define MASK_STRICT_ALIGN 0x20000000 /* Set STRICT_ALIGNMENT to 1. */ #define MASK_RELOCATABLE 0x10000000 /* GOT pointers are PC relative */ -#define MASK_NO_TRACEBACK 0x08000000 /* eliminate traceback words */ +#define MASK_UNUSED 0x08000000 /* UNUSED, was no-traceback */ #define MASK_LITTLE_ENDIAN 0x04000000 /* target is little endian */ -#define MASK_AIX_CALLS 0x02000000 /* Use AIX calling sequence */ +#define MASK_CALLS_1 0x02000000 /* First ABI bit (AIX, AIXDESC) */ #define MASK_PROTOTYPE 0x01000000 /* Only prototyped fcns pass variable args */ +#define MASK_CALLS_2 0x00800000 /* Second ABI bit (NT) */ + +#define MASK_CALLS (MASK_CALLS_1 | MASK_CALLS_2) +#define MASK_CALLS_V4 0 +#define MASK_CALLS_AIX MASK_CALLS_1 +#define MASK_CALLS_NT MASK_CALLS_2 +#define MASK_CALLS_AIXDESC MASK_CALLS #define TARGET_NO_BITFIELD_TYPE (target_flags & MASK_NO_BITFIELD_TYPE) #define TARGET_STRICT_ALIGN (target_flags & MASK_STRICT_ALIGN) #define TARGET_RELOCATABLE (target_flags & MASK_RELOCATABLE) -#define TARGET_NO_TRACEBACK (target_flags & MASK_NO_TRACEBACK) #define TARGET_LITTLE_ENDIAN (target_flags & MASK_LITTLE_ENDIAN) -#define TARGET_AIX_CALLS (target_flags & MASK_AIX_CALLS) #define TARGET_PROTOTYPE (target_flags & MASK_PROTOTYPE) -#define TARGET_TOC (target_flags & (MASK_64BIT \ +#define TARGET_TOC ((target_flags & (MASK_64BIT \ | MASK_RELOCATABLE \ - | MASK_MINIMAL_TOC)) + | MASK_MINIMAL_TOC)) \ + || DEFAULT_ABI == ABI_AIX \ + || DEFAULT_ABI == ABI_NT) #define TARGET_BITFIELD_TYPE (! TARGET_NO_BITFIELD_TYPE) -#define TARGET_TRACEBACK (! TARGET_NO_TRACEBACK) #define TARGET_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN) -#define TARGET_NO_AIX_CALLS (! TARGET_AIX_CALLS) #define TARGET_NO_PROTOTYPE (! TARGET_PROTOTYPE) #define TARGET_NO_TOC (! TARGET_TOC) -#define TARGET_V4_CALLS TARGET_NO_AIX_CALLS +#define TARGET_AIX_CALLS (target_flags & MASK_CALLS_1) /* either -mcall-aix or -mcall-aixdesc */ +#define TARGET_V4_CALLS ((target_flags & MASK_CALLS) == MASK_CALLS_V4) +#define TARGET_NT_CALLS ((target_flags & MASK_CALLS) == MASK_CALLS_NT) +#define TARGET_AIXDESC_CALLS ((target_flags & MASK_CALLS) == MASK_CALLS_AIXDESC) /* Pseudo target to indicate whether the object format is ELF (to get around not having conditional compilation in the md file) */ @@ -64,8 +72,8 @@ Boston, MA 02111-1307, USA. */ { "no-strict-align", -MASK_STRICT_ALIGN }, \ { "relocatable", MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC }, \ { "no-relocatable", -MASK_RELOCATABLE }, \ - { "traceback", -MASK_NO_TRACEBACK }, \ - { "no-traceback", MASK_NO_TRACEBACK }, \ + { "relocatable-lib", MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC }, \ + { "no-relocatable-lib", -MASK_RELOCATABLE }, \ { "little-endian", MASK_LITTLE_ENDIAN }, \ { "little", MASK_LITTLE_ENDIAN }, \ { "big-endian", -MASK_LITTLE_ENDIAN }, \ @@ -73,10 +81,19 @@ Boston, MA 02111-1307, USA. */ { "no-toc", 0 }, \ { "toc", MASK_MINIMAL_TOC }, \ { "full-toc", MASK_MINIMAL_TOC }, \ - { "call-aix", MASK_AIX_CALLS }, \ - { "call-sysv", -MASK_AIX_CALLS }, \ + { "call-aix", MASK_CALLS_AIX }, \ + { "call-aix", -MASK_CALLS_NT }, \ + { "call-aixdesc", MASK_CALLS_AIXDESC }, \ + { "call-aixdesc", -MASK_LITTLE_ENDIAN }, \ + { "call-sysv", -MASK_CALLS }, \ + { "call-nt", MASK_CALLS_NT | MASK_LITTLE_ENDIAN }, \ + { "call-nt", -MASK_CALLS_AIX }, \ { "prototype", MASK_PROTOTYPE }, \ - { "no-prototype", -MASK_PROTOTYPE }, + { "no-prototype", -MASK_PROTOTYPE }, \ + { "no-traceback", 0 }, \ + { "sim", 0 }, \ + { "mvme", 0 }, \ + { "emb", 0 }, \ /* Sometimes certain combinations of command options do not make sense on a particular target machine. You can define a macro @@ -94,8 +111,40 @@ do { \ target_flags |= MASK_MINIMAL_TOC; \ error ("-mrelocatable and -mno-minimal-toc are incompatible."); \ } \ + \ + if (TARGET_RELOCATABLE && TARGET_AIXDESC_CALLS) \ + { \ + target_flags &= ~MASK_RELOCATABLE; \ + error ("-mrelocatable and -mcall-aixdesc are incompatible."); \ + } \ + \ + if (TARGET_RELOCATABLE && TARGET_NT_CALLS) \ + { \ + target_flags &= ~MASK_MINIMAL_TOC; \ + error ("-mrelocatable and -mcall-nt are incompatible."); \ + } \ + \ + if (TARGET_AIXDESC_CALLS && TARGET_LITTLE_ENDIAN) \ + { \ + target_flags &= ~MASK_LITTLE_ENDIAN; \ + error ("-mcall-aixdesc must be big endian"); \ + } \ + \ + if (TARGET_NT_CALLS && TARGET_BIG_ENDIAN) \ + { \ + target_flags |= MASK_LITTLE_ENDIAN; \ + error ("-mcall-nt must be little endian"); \ + } \ + \ + rs6000_current_abi = ((TARGET_AIXDESC_CALLS) ? ABI_AIX : \ + (TARGET_NT_CALLS) ? ABI_NT : \ + (TARGET_AIX_CALLS) ? ABI_AIX_NODESC : \ + ABI_V4); \ } while (0) +/* Default ABI to compile code for */ +#define DEFAULT_ABI rs6000_current_abi + #include "rs6000/powerpc.h" /* System V.4 uses register 13 as a pointer to the small data area, @@ -152,12 +201,6 @@ do { \ #undef OBJECT_FORMAT_COFF -/* The XCOFF support uses weird symbol suffixes, which we don't want - for ELF. */ - -#undef RS6000_OUTPUT_BASENAME -#define RS6000_OUTPUT_BASENAME(FILE, NAME) assemble_name (FILE, NAME) - /* Don't bother to output .extern pseudo-ops. They are not needed by ELF assemblers. */ @@ -237,12 +280,39 @@ toc_section () \ if (in_section != in_toc) \ { \ in_section = in_toc; \ - fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \ - if (! toc_initialized) \ + if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT) \ + && TARGET_MINIMAL_TOC \ + && !TARGET_RELOCATABLE) \ + { \ + if (! toc_initialized) \ + { \ + toc_initialized = 1; \ + fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP); \ + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LCTOC", 0); \ + fprintf (asm_out_file, "\t.tc "); \ + ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1[TC],"); \ + ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \ + fprintf (asm_out_file, "\n"); \ + \ + fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \ + ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \ + fprintf (asm_out_file, " = .+32768\n"); \ + } \ + else \ + fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \ + } \ + else if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT) \ + && !TARGET_RELOCATABLE) \ + fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP); \ + else \ { \ - ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \ - fprintf (asm_out_file, " = .+32768\n"); \ - toc_initialized = 1; \ + fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \ + if (! toc_initialized) \ + { \ + ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \ + fprintf (asm_out_file, " = .+32768\n"); \ + toc_initialized = 1; \ + } \ } \ } \ } @@ -260,6 +330,30 @@ toc_section () \ const_section (); \ } +/* Return non-zero if this entry is to be written into the constant pool + in a special way. We do so if this is a SYMBOL_REF, LABEL_REF or a CONST + containing one of them. If -mfp-in-toc (the default), we also do + this for floating-point constants. We actually can only do this + if the FP formats of the target and host machines are the same, but + we can't check that since not every file that uses + GO_IF_LEGITIMATE_ADDRESS_P includes real.h. + + Unlike AIX, we don't key off of -mmininal-toc, but instead do not + allow floating point constants in the TOC if -mrelocatable. */ + +#undef ASM_OUTPUT_SPECIAL_POOL_ENTRY_P +#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X) \ + (TARGET_TOC \ + && (GET_CODE (X) == SYMBOL_REF \ + || (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS \ + && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF) \ + || GET_CODE (X) == LABEL_REF \ + || (!TARGET_NO_FP_IN_TOC \ + && !TARGET_RELOCATABLE \ + && GET_CODE (X) == CONST_DOUBLE \ + && GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ + && BITS_PER_WORD == HOST_BITS_PER_INT))) + /* These macros generate the special .type and .size directives which are used to set the corresponding fields of the linker symbol table entries in an ELF object file under SVR4. These macros also output @@ -269,37 +363,53 @@ toc_section () \ Some svr4 assemblers need to also have something extra said about the function's return value. We allow for that here. */ -extern void svr4_traceback (); extern int rs6000_pic_labelno; #undef ASM_DECLARE_FUNCTION_NAME #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ do { \ + char *orig_name; \ + char *init_ptr = (TARGET_64BIT) ? ".quad" : ".long"; \ + STRIP_NAME_ENCODING (orig_name, NAME); \ + \ if (TARGET_RELOCATABLE && get_pool_size () != 0) \ { \ - char buf[256]; \ + char buf[256], *buf_ptr; \ \ ASM_OUTPUT_INTERNAL_LABEL (FILE, "LCL", rs6000_pic_labelno); \ \ ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1); \ - fprintf (FILE, (TARGET_POWERPC64) ? "\t.quad " : "\t.long "); \ - assemble_name (FILE, buf); \ - putc ('-', FILE); \ + STRIP_NAME_ENCODING (buf_ptr, buf); \ + fprintf (FILE, "\t%s %s-", init_ptr, buf_ptr); \ \ ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno); \ - assemble_name (FILE, buf); \ - putc ('\n', FILE); \ + fprintf (FILE, "%s\n", buf_ptr); \ } \ \ - fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ - assemble_name (FILE, NAME); \ - putc (',', FILE); \ + fprintf (FILE, "\t%s\t %s,", TYPE_ASM_OP, orig_name); \ fprintf (FILE, TYPE_OPERAND_FMT, "function"); \ putc ('\n', FILE); \ - if (TARGET_TRACEBACK) \ - svr4_traceback (FILE, NAME, DECL); \ ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \ - ASM_OUTPUT_LABEL(FILE, NAME); \ + \ + if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT) \ + { \ + char *desc_name = orig_name; \ + \ + while (*desc_name == '.') \ + desc_name++; \ + \ + if (TREE_PUBLIC (DECL)) \ + fprintf (FILE, "\t.globl %s\n", desc_name); \ + \ + fprintf (FILE, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \ + fprintf (FILE, "%s:\n", desc_name); \ + fprintf (FILE, "\t%s %s\n", init_ptr, orig_name); \ + fprintf (FILE, "\t%s _GLOBAL_OFFSET_TABLE_\n", init_ptr); \ + if (DEFAULT_ABI == ABI_AIX) \ + fprintf (FILE, "\t%s 0\n", init_ptr); \ + fprintf (FILE, "\t.previous\n"); \ + } \ + fprintf (FILE, "%s:\n", orig_name); \ } while (0) /* How to renumber registers for dbx and gdb. */ @@ -315,11 +425,30 @@ extern int rs6000_pic_labelno; /* Pass -mppc to the assembler, since that is what powerpc.h currently implies. */ #undef ASM_SPEC -#define ASM_SPEC \ - "-u \ -%{mcpu=601: -m601} %{!mcpu=601: -mppc} \ +#define ASM_SPEC "\ +-u \ +%{!mcpu*: \ + %{mpower2: -mpwrx} \ + %{mpowerpc*: %{!mpower: -mppc}} \ + %{mno-powerpc: %{!mpower: %{!mpower2: -mcom}}} \ + %{mno-powerpc: %{mpower: %{!mpower2: -mpwr}}} \ + %{!mno-powerpc: %{mpower: -m601}} \ + %{!mno-powerpc: %{!mpower: -mppc}}} \ +%{mcpu=common: -mcom} \ +%{mcpu=power: -mpwr} \ +%{mcpu=powerpc: -mppc} \ +%{mcpu=rios: -mpwr} \ +%{mcpu=rios1: -mpwr} \ +%{mcpu=rios2: -mpwrx} \ +%{mcpu=rsc: -mpwr} \ +%{mcpu=rsc1: -mpwr} \ +%{mcpu=403: -mppc} \ +%{mcpu=601: -m601} \ +%{mcpu=603: -mppc} \ +%{mcpu=603e: -mppc} \ +%{mcpu=604: -mppc} \ %{V} %{v:%{!V:-V}} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \ -%{mrelocatable} \ +%{mrelocatable} %{mrelocatable-lib} %{memb} \ %{mlittle} %{mlittle-endian} %{mbig} %{mbig-endian}" /* Output .file and comments listing what options there are */ @@ -330,6 +459,61 @@ do { \ output_file_directive ((FILE), main_input_filename); \ } while (0) + +/* This is how to output an assembler line defining an `int' constant. + For -mrelocatable, we mark all addresses that need to be fixed up + in the .fixup section. */ +#undef ASM_OUTPUT_INT +#define ASM_OUTPUT_INT(FILE,VALUE) \ +do { \ + static int recurse = 0; \ + if (TARGET_RELOCATABLE \ + && in_section != in_toc \ + && in_section != in_text \ + && in_section != in_ctors \ + && in_section != in_dtors \ + && !recurse \ + && GET_CODE (VALUE) != CONST_INT \ + && GET_CODE (VALUE) != CONST_DOUBLE \ + && CONSTANT_P (VALUE)) \ + { \ + static int labelno = 0; \ + char buf[256], *p; \ + \ + recurse = 1; \ + ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", labelno++); \ + STRIP_NAME_ENCODING (p, buf); \ + fprintf (FILE, "%s:\n", p); \ + fprintf (FILE, "\t.long ("); \ + output_addr_const (FILE, (VALUE)); \ + fprintf (FILE, ")@fixup\n"); \ + fprintf (FILE, "\t.section\t\".fixup\",\"aw\"\n"); \ + ASM_OUTPUT_ALIGN (FILE, 2); \ + fprintf (FILE, "\t.long\t%s\n", p); \ + fprintf (FILE, "\t.previous\n"); \ + recurse = 0; \ + } \ + /* Remove initial .'s to turn a -mcall-aixdesc or -mcall-nt function \ + address into the address of the descriptor, not the function \ + itself. */ \ + else if (GET_CODE (VALUE) == SYMBOL_REF \ + && XSTR (VALUE, 0)[0] == '.' \ + && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)) \ + { \ + char *name = XSTR (VALUE, 0); \ + while (*name == '.') \ + name++; \ + \ + fprintf (FILE, "\t.long %s\n", name); \ + } \ + else \ + { \ + fprintf (FILE, "\t.long "); \ + output_addr_const (FILE, (VALUE)); \ + fprintf (FILE, "\n"); \ + } \ +} while (0) + /* This is the end of what might become sysv4.h. */ /* Allow stabs and dwarf, prefer dwarf. */ @@ -337,6 +521,35 @@ do { \ #define DBX_DEBUGGING_INFO #define DWARF_DEBUGGING_INFO +/* If we are referencing a function that is static or is known to be + in this file, make the SYMBOL_REF special. We can use this to indicate + that we can branch to this function without emitting a no-op after the + call. For real AIX and NT calling sequences, we also replace the + function name with the real name (1 or 2 leading .'s), rather than + the function descriptor name. This saves a lot of overriding code + to readd the prefixes. */ + +#undef ENCODE_SECTION_INFO +#define ENCODE_SECTION_INFO(DECL) \ + do { \ + if (TREE_CODE (DECL) == FUNCTION_DECL) \ + { \ + rtx sym_ref = XEXP (DECL_RTL (DECL), 0); \ + if (TREE_ASM_WRITTEN (DECL) || ! TREE_PUBLIC (DECL)) \ + SYMBOL_REF_FLAG (sym_ref) = 1; \ + \ + if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT) \ + { \ + char *prefix = (DEFAULT_ABI == ABI_AIX) ? "." : ".."; \ + char *str = permalloc (strlen (prefix) + 1 \ + + strlen (XSTR (sym_ref, 0))); \ + strcpy (str, prefix); \ + strcat (str, XSTR (sym_ref, 0)); \ + XSTR (sym_ref, 0) = str; \ + } \ + } \ + } while (0) + /* This macro gets just the user-specified name out of the string in a SYMBOL_REF. Discard a leading * */ @@ -344,24 +557,6 @@ do { \ #define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \ (VAR) = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*')) -/* Like block addresses, stabs line numbers are relative to the - current function. */ - -#undef ASM_OUTPUT_SOURCE_LINE -#define ASM_OUTPUT_SOURCE_LINE(file, line) \ -do \ - { \ - static int sym_lineno = 1; \ - char *_p; \ - fprintf (file, "\t.stabn 68,0,%d,.LM%d-", \ - line, sym_lineno); \ - STRIP_NAME_ENCODING (_p, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \ - assemble_name (file, _p); \ - fprintf (file, "\n.LM%d:\n", sym_lineno); \ - sym_lineno += 1; \ - } \ -while (0) - /* But, to make this work, we have to output the stabs for the function name *first*... */ @@ -371,77 +566,6 @@ while (0) #undef TARGET_VERSION #define TARGET_VERSION fprintf (stderr, " (PowerPC System V.4)"); - - -/* Output assembler code for a block containing the constant parts - of a trampoline, leaving space for the variable parts. - - The trampoline should set the static chain pointer to value placed - into the trampoline and should branch to the specified routine. - - Unlike AIX, this needs real code. */ - -#undef TRAMPOLINE_TEMPLATE -#define TRAMPOLINE_TEMPLATE(FILE) \ -do { \ - char *sc = reg_names[STATIC_CHAIN_REGNUM]; \ - char *r0 = reg_names[0]; \ - \ - if (STATIC_CHAIN_REGNUM == 0 || !TARGET_NEW_MNEMONICS) \ - abort (); \ - \ - if (TARGET_64BIT) \ - { \ - fprintf (FILE, "\tmflr %s\n", r0); /* offset 0 */ \ - fprintf (FILE, "\tbl .LTRAMP1\n"); /* offset 4 */ \ - fprintf (FILE, "\t.long 0,0,0,0\n"); /* offset 8 */ \ - fprintf (FILE, ".LTRAMP1:\n"); \ - fprintf (FILE, "\tmflr %s\n", sc); /* offset 28 */ \ - fprintf (FILE, "\tmtlr %s\n", r0); /* offset 32 */ \ - fprintf (FILE, "\tld %s,0(%s)\n", r0, sc); /* offset 36 */ \ - fprintf (FILE, "\tld %s,8(%s)\n", sc, sc); /* offset 40 */ \ - fprintf (FILE, "\tmtctr %s\n", r0); /* offset 44 */ \ - fprintf (FILE, "\tbctr\n"); /* offset 48 */ \ - } \ - else \ - { \ - fprintf (FILE, "\tmflr %s\n", r0); /* offset 0 */ \ - fprintf (FILE, "\tbl .LTRAMP1\n"); /* offset 4 */ \ - fprintf (FILE, "\t.long 0,0\n"); /* offset 8 */ \ - fprintf (FILE, ".LTRAMP1:\n"); \ - fprintf (FILE, "\tmflr %s\n", sc); /* offset 20 */ \ - fprintf (FILE, "\tmtlr %s\n", r0); /* offset 24 */ \ - fprintf (FILE, "\tlwz %s,0(%s)\n", r0, sc); /* offset 28 */ \ - fprintf (FILE, "\tlwz %s,4(%s)\n", sc, sc); /* offset 32 */ \ - fprintf (FILE, "\tmtctr %s\n", r0); /* offset 36 */ \ - fprintf (FILE, "\tbctr\n"); /* offset 40 */ \ - } \ -} while (0) - -/* Length in units of the trampoline for entering a nested function. */ - -#undef TRAMPOLINE_SIZE -#define TRAMPOLINE_SIZE (TARGET_64BIT ? 48 : 40) - -/* 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. */ - -#undef INITIALIZE_TRAMPOLINE -#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, CXT) \ -{ \ - rtx reg = gen_reg_rtx (Pmode); \ - \ - emit_move_insn (reg, FNADDR); \ - emit_move_insn (gen_rtx (MEM, Pmode, \ - plus_constant (ADDR, 8)), \ - reg); \ - emit_move_insn (gen_rtx (MEM, Pmode, \ - plus_constant (ADDR, (TARGET_64BIT ? 16 : 12))), \ - CXT); \ - emit_insn (gen_sync_isync (gen_rtx (MEM, BLKmode, ADDR))); \ -} - #undef CPP_PREDEFINES #define CPP_PREDEFINES \ @@ -482,7 +606,9 @@ do { \ #define CPP_SPEC "\ %{posix: -D_POSIX_SOURCE} \ %{mrelocatable: -D_RELOCATABLE} \ -%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \ +%{mcall-sysv: -D_CALL_SYSV} %{mcall-nt: -D_CALL_NT} \ +%{mcall-aix: -D_CALL_AIX} %{mcall-aixdesc: -D_CALL_AIX -D_CALL_AIXDESC} \ +%{!mcall-sysv: %{!mcall-aix: %{!mcall-aixdesc: %{!mcall-nt: -D_CALL_SYSV}}}} \ %{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \ %{mlittle: -D_LITTLE_ENDIAN -Amachine(littleendian)} \ %{mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)} \ @@ -503,5 +629,20 @@ do { \ %{mcpu=rsc1: -D_ARCH_PWR} \ %{mcpu=403: -D_ARCH_PPC} \ %{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \ +%{mcpu=602: -D_ARCH_PPC} \ %{mcpu=603: -D_ARCH_PPC} \ -%{mcpu=604: -D_ARCH_PPC}" +%{mcpu=603e: -D_ARCH_PPC} \ +%{mcpu=604: -D_ARCH_PPC} \ +%{mcpu=620: -D_ARCH_PPC}" + +/* Define this macro as a C expression for the initializer of an + array of string to tell the driver program which options are + defaults for this target and thus do not need to be handled + specially when using `MULTILIB_OPTIONS'. + + Do not define this macro if `MULTILIB_OPTIONS' is not defined in + the target makefile fragment or if none of the options listed in + `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */ + +#undef MULTILIB_DEFAULTS +#define MULTILIB_DEFAULTS { "mbig", "mbig-endian", "mcall-sysv" } diff --git a/gcc/config/rs6000/sysv4le.h b/gcc/config/rs6000/sysv4le.h index 59bd1b72c83..7a2e55b6b7c 100644 --- a/gcc/config/rs6000/sysv4le.h +++ b/gcc/config/rs6000/sysv4le.h @@ -29,7 +29,9 @@ Boston, MA 02111-1307, USA. */ #define CPP_SPEC "\ %{posix: -D_POSIX_SOURCE} \ %{mrelocatable: -D_RELOCATABLE} \ -%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \ +%{mcall-sysv: -D_CALL_SYSV} %{mcall-nt: -D_CALL_NT} \ +%{mcall-aix: -D_CALL_AIX} %{mcall-aixdesc: -D_CALL_AIX -D_CALL_AIXDESC} \ +%{!mcall-sysv: %{!mcall-aix: %{!mcall-aixdesc: %{!mcall-nt: -D_CALL_SYSV}}}} \ %{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \ %{mbig: -D_BIG_ENDIAN -Amachine(bigendian)} \ %{mbig-endian: -D_BIG_ENDIAN -Amachine(bigendian)} \ @@ -50,5 +52,20 @@ Boston, MA 02111-1307, USA. */ %{mcpu=rsc1: -D_ARCH_PWR} \ %{mcpu=403: -D_ARCH_PPC} \ %{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \ +%{mcpu=602: -D_ARCH_PPC} \ %{mcpu=603: -D_ARCH_PPC} \ -%{mcpu=604: -D_ARCH_PPC}" +%{mcpu=603e: -D_ARCH_PPC} \ +%{mcpu=604: -D_ARCH_PPC} \ +%{mcpu=620: -D_ARCH_PPC}" + +/* Define this macro as a C expression for the initializer of an + array of string to tell the driver program which options are + defaults for this target and thus do not need to be handled + specially when using `MULTILIB_OPTIONS'. + + Do not define this macro if `MULTILIB_OPTIONS' is not defined in + the target makefile fragment or if none of the options listed in + `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */ + +#undef MULTILIB_DEFAULTS +#define MULTILIB_DEFAULTS { "mlittle", "mlittle-endian", "mcall-sysv" } diff --git a/gcc/config/rs6000/t-ppc b/gcc/config/rs6000/t-ppc index 5fcb3d870e3..e664aa5053c 100644 --- a/gcc/config/rs6000/t-ppc +++ b/gcc/config/rs6000/t-ppc @@ -2,6 +2,8 @@ LIBGCC1 = CROSS_LIBGCC1 = +EXTRA_HEADERS = $(srcdir)/ginclude/ppc-asm.h + # These are really part of libgcc1, but this will cause them to be # built correctly, so... [taken from t-sparclite] LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c diff --git a/gcc/config/rs6000/t-ppcgas b/gcc/config/rs6000/t-ppcgas index db4b936dcbf..1169ef69c89 100644 --- a/gcc/config/rs6000/t-ppcgas +++ b/gcc/config/rs6000/t-ppcgas @@ -2,6 +2,8 @@ LIBGCC1 = CROSS_LIBGCC1 = +EXTRA_HEADERS = $(srcdir)/ginclude/ppc-asm.h + # These are really part of libgcc1, but this will cause them to be # built correctly, so... [taken from t-sparclite] LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c @@ -16,15 +18,18 @@ fp-bit.c: $(srcdir)/config/fp-bit.c # Build libgcc.a with different options. MULTILIB_OPTIONS = msoft-float \ - mlittle + mlittle/mbig \ + mcall-sysv/mcall-aix/mcall-aixdesc MULTILIB_DIRNAMES = soft-float \ - little-endian + little big \ + sysv aix aixdesc MULTILIB_MATCHES = mlittle=mlittle-endian \ - msoft-float=mcpu?403 \ - msoft-float=mcpu?mpc403 \ - msoft-float=mcpu?ppc403 + mbig=mbig-endian \ + msoft-float=mcpu?403 + +MULTILIB_EXCEPTIONS = *mlittle/*mcall-aixdesc* LIBGCC = stmp-multilib INSTALL_LIBGCC = install-multilib -- 2.30.2