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