1/* Machine description patterns for PowerPC running Darwin (Mac OS X). 2 Copyright (C) 2004-2020 Free Software Foundation, Inc. 3 Contributed by Apple Computer Inc. 4 5This file is part of GCC. 6 7GNU CC is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3, or (at your option) 10any later version. 11 12GNU CC is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18;; along with GCC; see the file COPYING3. If not see 19;; <http://www.gnu.org/licenses/>. */ 20 21(define_insn "adddi3_high" 22 [(set (match_operand:DI 0 "gpc_reg_operand" "=b") 23 (plus:DI (match_operand:DI 1 "gpc_reg_operand" "b") 24 (high:DI (match_operand 2 "" ""))))] 25 "TARGET_MACHO && TARGET_64BIT" 26 "addis %0,%1,ha16(%2)") 27 28(define_insn "movdf_low_si" 29 [(set (match_operand:DF 0 "gpc_reg_operand" "=f,!r") 30 (mem:DF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b") 31 (match_operand 2 "" ""))))] 32 "TARGET_MACHO && TARGET_HARD_FLOAT && !TARGET_64BIT" 33{ 34 switch (which_alternative) 35 { 36 case 0: 37 return "lfd %0,lo16(%2)(%1)"; 38 case 1: 39 { 40 if (TARGET_POWERPC64 && TARGET_32BIT) 41 /* Note, old assemblers didn't support relocation here. */ 42 return "ld %0,lo16(%2)(%1)"; 43 else 44 { 45 output_asm_insn ("la %0,lo16(%2)(%1)", operands); 46 output_asm_insn ("lwz %L0,4(%0)", operands); 47 return ("lwz %0,0(%0)"); 48 } 49 } 50 default: 51 gcc_unreachable (); 52 } 53} 54 [(set_attr "type" "load") 55 (set_attr "length" "4,12")]) 56 57 58(define_insn "movdf_low_di" 59 [(set (match_operand:DF 0 "gpc_reg_operand" "=f,!r") 60 (mem:DF (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,b") 61 (match_operand 2 "" ""))))] 62 "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_64BIT" 63 "@ 64 lfd %0,lo16(%2)(%1) 65 ld %0,lo16(%2)(%1)" 66 [(set_attr "type" "load")]) 67 68(define_insn "movdf_low_st_si" 69 [(set (mem:DF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b") 70 (match_operand 2 "" ""))) 71 (match_operand:DF 0 "gpc_reg_operand" "f"))] 72 "TARGET_MACHO && TARGET_HARD_FLOAT && ! TARGET_64BIT" 73 "stfd %0,lo16(%2)(%1)" 74 [(set_attr "type" "store")]) 75 76(define_insn "movdf_low_st_di" 77 [(set (mem:DF (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b") 78 (match_operand 2 "" ""))) 79 (match_operand:DF 0 "gpc_reg_operand" "f"))] 80 "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_64BIT" 81 "stfd %0,lo16(%2)(%1)" 82 [(set_attr "type" "store")]) 83 84(define_insn "movsf_low_si" 85 [(set (match_operand:SF 0 "gpc_reg_operand" "=f,!r") 86 (mem:SF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b") 87 (match_operand 2 "" ""))))] 88 "TARGET_MACHO && TARGET_HARD_FLOAT && ! TARGET_64BIT" 89 "@ 90 lfs %0,lo16(%2)(%1) 91 lwz %0,lo16(%2)(%1)" 92 [(set_attr "type" "load")]) 93 94(define_insn "movsf_low_di" 95 [(set (match_operand:SF 0 "gpc_reg_operand" "=f,!r") 96 (mem:SF (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,b") 97 (match_operand 2 "" ""))))] 98 "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_64BIT" 99 "@ 100 lfs %0,lo16(%2)(%1) 101 lwz %0,lo16(%2)(%1)" 102 [(set_attr "type" "load")]) 103 104(define_insn "movsf_low_st_si" 105 [(set (mem:SF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b") 106 (match_operand 2 "" ""))) 107 (match_operand:SF 0 "gpc_reg_operand" "f,!r"))] 108 "TARGET_MACHO && TARGET_HARD_FLOAT && ! TARGET_64BIT" 109 "@ 110 stfs %0,lo16(%2)(%1) 111 stw %0,lo16(%2)(%1)" 112 [(set_attr "type" "store")]) 113 114(define_insn "movsf_low_st_di" 115 [(set (mem:SF (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,b") 116 (match_operand 2 "" ""))) 117 (match_operand:SF 0 "gpc_reg_operand" "f,!r"))] 118 "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_64BIT" 119 "@ 120 stfs %0,lo16(%2)(%1) 121 stw %0,lo16(%2)(%1)" 122 [(set_attr "type" "store")]) 123 124;; Mach-O PIC. 125 126(define_insn "@macho_high_<mode>" 127 [(set (match_operand:P 0 "gpc_reg_operand" "=b*r") 128 (high:P (match_operand 1 "" "")))] 129 "TARGET_MACHO && (DEFAULT_ABI == ABI_DARWIN) && !flag_pic" 130 "lis %0,ha16(%1)") 131 132(define_insn "@macho_low_<mode>" 133 [(set (match_operand:P 0 "gpc_reg_operand" "=r") 134 (lo_sum:P (match_operand:P 1 "gpc_reg_operand" "b") 135 (match_operand 2 "" "")))] 136 "TARGET_MACHO && (DEFAULT_ABI == ABI_DARWIN) && !flag_pic" 137 "la %0,lo16(%2)(%1)") 138 139(define_insn "@machopic_high_<mode>" 140 [(set (match_operand:P 0 "gpc_reg_operand" "=b*r") 141 (high:P (match_operand 1 "macho_pic_address" "")))] 142 "TARGET_MACHO && flag_pic" 143 "lis %0,ha16(%1)") 144 145(define_insn "@machopic_low_<mode>" 146 [(set (match_operand:P 0 "gpc_reg_operand" "=r") 147 (lo_sum:P (match_operand:P 1 "gpc_reg_operand" "b") 148 (match_operand 2 "macho_pic_address" "")))] 149 "TARGET_MACHO && flag_pic" 150 "la %0,lo16(%2)(%1)") 151 152(define_split 153 [(set (mem:V4SI (plus:DI (match_operand:DI 0 "gpc_reg_operand") 154 (match_operand:DI 1 "short_cint_operand"))) 155 (match_operand:V4SI 2 "register_operand")) 156 (clobber (match_operand:DI 3 "gpc_reg_operand"))] 157 "TARGET_MACHO && TARGET_64BIT" 158 [(set (match_dup 3) (plus:DI (match_dup 0) (match_dup 1))) 159 (set (mem:V4SI (match_dup 3)) 160 (match_dup 2))] 161 "") 162 163(define_insn "@macho_correct_pic_<mode>" 164 [(set (match_operand:P 0 "gpc_reg_operand" "=r") 165 (plus:P (match_operand:P 1 "gpc_reg_operand" "r") 166 (unspec:P [(match_operand:P 2 "immediate_operand" "s") 167 (match_operand:P 3 "immediate_operand" "s")] 168 UNSPEC_MPIC_CORRECT)))] 169 "DEFAULT_ABI == ABI_DARWIN" 170 "addis %0,%1,ha16(%2-%3)\n\taddi %0,%0,lo16(%2-%3)" 171 [(set_attr "length" "8")]) 172 173(define_insn "@load_macho_picbase_<mode>" 174 [(set (reg:P LR_REGNO) 175 (unspec:P [(match_operand:P 0 "immediate_operand" "s") 176 (pc)] UNSPEC_LD_MPIC))] 177 "(DEFAULT_ABI == ABI_DARWIN) && flag_pic" 178{ 179#if TARGET_MACHO 180 machopic_should_output_picbase_label (); /* Update for new func. */ 181#else 182 gcc_unreachable (); 183#endif 184 return "bcl 20,31,%0\n%0:"; 185} 186 [(set_attr "type" "branch") 187 (set_attr "cannot_copy" "yes")]) 188 189(define_insn "@reload_macho_picbase_<mode>" 190 [(set (reg:P LR_REGNO) 191 (unspec:P [(match_operand:P 0 "immediate_operand" "s") 192 (pc)] UNSPEC_RELD_MPIC))] 193 "(DEFAULT_ABI == ABI_DARWIN) && flag_pic" 194{ 195#if TARGET_MACHO 196 if (machopic_should_output_picbase_label ()) 197 { 198 static char tmp[64]; 199 const char *cnam = machopic_get_function_picbase (); 200 snprintf (tmp, 64, "bcl 20,31,%s\n%s:\n%%0:", cnam, cnam); 201 return tmp; 202 } 203 else 204#else 205 gcc_unreachable (); 206#endif 207 return "bcl 20,31,%0\n%0:"; 208} 209 [(set_attr "type" "branch") 210 (set_attr "cannot_copy" "yes")]) 211 212;; We need to restore the PIC register, at the site of nonlocal label. 213 214(define_insn_and_split "nonlocal_goto_receiver" 215 [(unspec_volatile [(const_int 0)] UNSPECV_NLGR)] 216 "TARGET_MACHO && flag_pic" 217 "#" 218 "&& reload_completed" 219 [(const_int 0)] 220{ 221#if TARGET_MACHO 222 if (crtl->uses_pic_offset_table) 223 { 224 static unsigned n = 0; 225 rtx picrtx = gen_rtx_SYMBOL_REF (Pmode, MACHOPIC_FUNCTION_BASE_NAME); 226 rtx picreg = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM); 227 rtx tmplrtx; 228 char tmplab[20]; 229 230 ASM_GENERATE_INTERNAL_LABEL(tmplab, "Lnlgr", ++n); 231 tmplrtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (tmplab)); 232 233 emit_insn (gen_reload_macho_picbase (Pmode, tmplrtx)); 234 emit_move_insn (picreg, gen_rtx_REG (Pmode, LR_REGNO)); 235 emit_insn (gen_macho_correct_pic (Pmode, picreg, picreg, 236 picrtx, tmplrtx)); 237 } 238 else 239 /* Not using PIC reg, no reload needed. */ 240 emit_note (NOTE_INSN_DELETED); 241#else 242 gcc_unreachable (); 243#endif 244 DONE; 245}) 246