1 /* Definitions for ia64-linux target. */ 2 3 /* This macro is a C statement to print on `stderr' a string describing the 4 particular machine description choice. */ 5 6 #define TARGET_VERSION fprintf (stderr, " (IA-64) Linux"); 7 8 /* This is for -profile to use -lc_p instead of -lc. */ 9 #undef CC1_SPEC 10 #define CC1_SPEC "%{profile:-p} %{G*}" 11 12 /* Target OS builtins. */ 13 #define TARGET_OS_CPP_BUILTINS() \ 14 do { \ 15 LINUX_TARGET_OS_CPP_BUILTINS(); \ 16 builtin_define("_LONGLONG"); \ 17 } while (0) 18 19 /* Need to override linux.h STARTFILE_SPEC, since it has crtbeginT.o in. */ 20 #undef STARTFILE_SPEC 21 #ifdef HAVE_LD_PIE 22 #define STARTFILE_SPEC \ 23 "%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}}\ 24 crti.o%s %{shared|pie:crtbeginS.o%s;:crtbegin.o%s}" 25 #else 26 #define STARTFILE_SPEC \ 27 "%{!shared: %{pg|p|profile:gcrt1.o%s;:crt1.o%s}}\ 28 crti.o%s %{shared|pie:crtbeginS.o%s;:crtbegin.o%s}" 29 #endif 30 31 /* Similar to standard Linux, but adding -ffast-math support. */ 32 #undef ENDFILE_SPEC 33 #define ENDFILE_SPEC \ 34 "%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \ 35 %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s" 36 37 /* Define this for shared library support because it isn't in the main 38 linux.h file. */ 39 40 #undef LINK_SPEC 41 #define LINK_SPEC "\ 42 %{shared:-shared} \ 43 %{!shared: \ 44 %{!static: \ 45 %{rdynamic:-export-dynamic} \ 46 %{!dynamic-linker:-dynamic-linker /lib/ld-linux-ia64.so.2}} \ 47 %{static:-static}}" 48 49 50 #define JMP_BUF_SIZE 76 51 52 /* Override linux.h LINK_EH_SPEC definition. 53 Signalize that because we have fde-glibc, we don't need all C shared libs 54 linked against -lgcc_s. */ 55 #undef LINK_EH_SPEC 56 #define LINK_EH_SPEC "" 57 58 /* Do code reading to identify a signal frame, and set the frame 59 state data appropriately. See unwind-dw2.c for the structs. */ 60 61 /* This works only for glibc-2.3 and later, because sigcontext is different 62 in glibc-2.2.4. */ 63 64 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) 65 66 #ifdef IN_LIBGCC2 67 #include <signal.h> 68 #include <sys/ucontext.h> 69 70 #define IA64_GATE_AREA_START 0xa000000000000100LL 71 #define IA64_GATE_AREA_END 0xa000000000030000LL 72 73 #define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \ 74 if ((CONTEXT)->rp >= IA64_GATE_AREA_START \ 75 && (CONTEXT)->rp < IA64_GATE_AREA_END) \ 76 { \ 77 struct sigframe { \ 78 char scratch[16]; \ 79 unsigned long sig_number; \ 80 struct siginfo *info; \ 81 struct sigcontext *sc; \ 82 } *frame_ = (struct sigframe *)(CONTEXT)->psp; \ 83 struct sigcontext *sc_ = frame_->sc; \ 84 \ 85 /* Restore scratch registers in case the unwinder needs to \ 86 refer to a value stored in one of them. */ \ 87 { \ 88 int i_; \ 89 \ 90 for (i_ = 2; i_ < 4; i_++) \ 91 (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \ 92 for (i_ = 8; i_ < 12; i_++) \ 93 (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \ 94 for (i_ = 14; i_ < 32; i_++) \ 95 (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \ 96 } \ 97 \ 98 (CONTEXT)->fpsr_loc = &(sc_->sc_ar_fpsr); \ 99 (CONTEXT)->pfs_loc = &(sc_->sc_ar_pfs); \ 100 (CONTEXT)->lc_loc = &(sc_->sc_ar_lc); \ 101 (CONTEXT)->unat_loc = &(sc_->sc_ar_unat); \ 102 (CONTEXT)->br_loc[0] = &(sc_->sc_br[0]); \ 103 (CONTEXT)->br_loc[6] = &(sc_->sc_br[6]); \ 104 (CONTEXT)->br_loc[7] = &(sc_->sc_br[7]); \ 105 (CONTEXT)->pr = sc_->sc_pr; \ 106 (CONTEXT)->psp = sc_->sc_gr[12]; \ 107 (CONTEXT)->gp = sc_->sc_gr[1]; \ 108 /* Signal frame doesn't have an associated reg. stack frame \ 109 other than what we adjust for below. */ \ 110 (FS) -> no_reg_stack_frame = 1; \ 111 \ 112 if (sc_->sc_rbs_base) \ 113 { \ 114 /* Need to switch from alternate register backing store. */ \ 115 long ndirty, loadrs = sc_->sc_loadrs >> 16; \ 116 unsigned long alt_bspstore = (CONTEXT)->bsp - loadrs; \ 117 unsigned long bspstore; \ 118 unsigned long *ar_bsp = (unsigned long *)(sc_->sc_ar_bsp); \ 119 \ 120 ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, \ 121 (unsigned long *) (CONTEXT)->bsp);\ 122 bspstore = (unsigned long) \ 123 ia64_rse_skip_regs (ar_bsp, -ndirty); \ 124 ia64_copy_rbs ((CONTEXT), bspstore, alt_bspstore, loadrs, \ 125 sc_->sc_ar_rnat); \ 126 } \ 127 \ 128 /* Don't touch the branch registers o.t. b0, b6 and b7. \ 129 The kernel doesn't pass the preserved branch registers \ 130 in the sigcontext but leaves them intact, so there's no \ 131 need to do anything with them here. */ \ 132 { \ 133 unsigned long sof = sc_->sc_cfm & 0x7f; \ 134 (CONTEXT)->bsp = (unsigned long) \ 135 ia64_rse_skip_regs ((unsigned long *)(sc_->sc_ar_bsp), -sof); \ 136 } \ 137 \ 138 (FS)->curr.reg[UNW_REG_RP].where = UNW_WHERE_SPREL; \ 139 (FS)->curr.reg[UNW_REG_RP].val \ 140 = (unsigned long)&(sc_->sc_ip) - (CONTEXT)->psp; \ 141 (FS)->curr.reg[UNW_REG_RP].when = -1; \ 142 \ 143 goto SUCCESS; \ 144 } 145 146 #define MD_HANDLE_UNWABI(CONTEXT, FS) \ 147 if ((FS)->unwabi == ((3 << 8) | 's') \ 148 || (FS)->unwabi == ((0 << 8) | 's')) \ 149 { \ 150 struct sigframe { \ 151 char scratch[16]; \ 152 unsigned long sig_number; \ 153 struct siginfo *info; \ 154 struct sigcontext *sc; \ 155 } *frame_ = (struct sigframe *)(CONTEXT)->psp; \ 156 struct sigcontext *sc_ = frame_->sc; \ 157 \ 158 /* Restore scratch registers in case the unwinder needs to \ 159 refer to a value stored in one of them. */ \ 160 { \ 161 int i_; \ 162 \ 163 for (i_ = 2; i_ < 4; i_++) \ 164 (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \ 165 for (i_ = 8; i_ < 12; i_++) \ 166 (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \ 167 for (i_ = 14; i_ < 32; i_++) \ 168 (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \ 169 } \ 170 \ 171 (CONTEXT)->pfs_loc = &(sc_->sc_ar_pfs); \ 172 (CONTEXT)->lc_loc = &(sc_->sc_ar_lc); \ 173 (CONTEXT)->unat_loc = &(sc_->sc_ar_unat); \ 174 (CONTEXT)->br_loc[0] = &(sc_->sc_br[0]); \ 175 (CONTEXT)->br_loc[6] = &(sc_->sc_br[6]); \ 176 (CONTEXT)->br_loc[7] = &(sc_->sc_br[7]); \ 177 (CONTEXT)->pr = sc_->sc_pr; \ 178 (CONTEXT)->gp = sc_->sc_gr[1]; \ 179 /* Signal frame doesn't have an associated reg. stack frame \ 180 other than what we adjust for below. */ \ 181 (FS) -> no_reg_stack_frame = 1; \ 182 \ 183 if (sc_->sc_rbs_base) \ 184 { \ 185 /* Need to switch from alternate register backing store. */ \ 186 long ndirty, loadrs = sc_->sc_loadrs >> 16; \ 187 unsigned long alt_bspstore = (CONTEXT)->bsp - loadrs; \ 188 unsigned long bspstore; \ 189 unsigned long *ar_bsp = (unsigned long *)(sc_->sc_ar_bsp); \ 190 \ 191 ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, \ 192 (unsigned long *) (CONTEXT)->bsp);\ 193 bspstore = (unsigned long) \ 194 ia64_rse_skip_regs (ar_bsp, -ndirty); \ 195 ia64_copy_rbs ((CONTEXT), bspstore, alt_bspstore, loadrs, \ 196 sc_->sc_ar_rnat); \ 197 } \ 198 \ 199 /* Don't touch the branch registers o.t. b0, b6 and b7. \ 200 The kernel doesn't pass the preserved branch registers \ 201 in the sigcontext but leaves them intact, so there's no \ 202 need to do anything with them here. */ \ 203 { \ 204 unsigned long sof = sc_->sc_cfm & 0x7f; \ 205 (CONTEXT)->bsp = (unsigned long) \ 206 ia64_rse_skip_regs ((unsigned long *)(sc_->sc_ar_bsp), -sof); \ 207 } \ 208 \ 209 /* pfs_loc already set above. Without this pfs_loc would point \ 210 incorrectly to sc_cfm instead of sc_ar_pfs. */ \ 211 (FS)->curr.reg[UNW_REG_PFS].where = UNW_WHERE_NONE; \ 212 } 213 214 #endif /* IN_LIBGCC2 */ 215 #endif /* glibc-2.3 or better */ 216