]>
Commit | Line | Data |
---|---|---|
16bea517 | 1 | /* Output routines for GCC for Hitachi Super-H. |
05a81fe5 | 2 | Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc. |
bc45ade3 | 3 | |
c15c9075 RK |
4 | This file is part of GNU CC. |
5 | ||
6 | GNU CC is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2, or (at your option) | |
9 | any later version. | |
10 | ||
11 | GNU CC is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GNU CC; see the file COPYING. If not, write to | |
18 | the Free Software Foundation, 59 Temple Place - Suite 330, | |
19 | Boston, MA 02111-1307, USA. */ | |
bc45ade3 | 20 | |
8aa2a305 JW |
21 | /* Contributed by Steve Chamberlain (sac@cygnus.com). |
22 | Improved by Jim Wilson (wilson@cygnus.com). */ | |
bc45ade3 | 23 | |
bc45ade3 | 24 | #include "config.h" |
8aa2a305 JW |
25 | |
26 | #include <stdio.h> | |
27 | ||
bc45ade3 | 28 | #include "rtl.h" |
bc45ade3 | 29 | #include "tree.h" |
bc45ade3 | 30 | #include "flags.h" |
8aa2a305 | 31 | #include "insn-flags.h" |
bc45ade3 | 32 | #include "expr.h" |
8aa2a305 JW |
33 | #include "regs.h" |
34 | #include "hard-reg-set.h" | |
35 | #include "output.h" | |
956a5206 | 36 | #include "insn-attr.h" |
bc45ade3 | 37 | |
00f8ff66 SC |
38 | #define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0) |
39 | #define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1) | |
40 | ||
20b04867 | 41 | /* ??? The pragma interrupt support will not work for SH3. */ |
8aa2a305 JW |
42 | /* This is set by #pragma interrupt and #pragma trapa, and causes gcc to |
43 | output code for the next function appropriate for an interrupt handler. */ | |
0d7e008e | 44 | int pragma_interrupt; |
bc45ade3 | 45 | |
8aa2a305 JW |
46 | /* This is set by #pragma trapa, and is similar to the above, except that |
47 | the compiler doesn't emit code to preserve all registers. */ | |
48 | static int pragma_trapa; | |
49 | ||
956a5206 JW |
50 | /* This is set by #pragma nosave_low_regs. This is useful on the SH3, |
51 | which has a separate set of low regs for User and Supervisor modes. | |
52 | This should only be used for the lowest level of interrupts. Higher levels | |
53 | of interrupts must save the registers in case they themselves are | |
54 | interrupted. */ | |
55 | int pragma_nosave_low_regs; | |
56 | ||
8aa2a305 JW |
57 | /* This is used for communication between SETUP_INCOMING_VARARGS and |
58 | sh_expand_prologue. */ | |
bc45ade3 | 59 | int current_function_anonymous_args; |
16bea517 | 60 | |
8aa2a305 JW |
61 | /* Global variables from toplev.c and final.c that are used within, but |
62 | not declared in any header file. */ | |
b9654711 | 63 | extern char *version_string; |
8aa2a305 | 64 | extern int *insn_addresses; |
00f8ff66 | 65 | |
bc45ade3 SC |
66 | /* Global variables for machine-dependent things. */ |
67 | ||
16bea517 JW |
68 | /* Which cpu are we scheduling for. */ |
69 | enum processor_type sh_cpu; | |
70 | ||
bc45ade3 | 71 | /* Saved operands from the last compare to use when we generate an scc |
16bea517 | 72 | or bcc insn. */ |
bc45ade3 SC |
73 | |
74 | rtx sh_compare_op0; | |
75 | rtx sh_compare_op1; | |
76 | ||
77 | /* Provides the class number of the smallest class containing | |
16bea517 | 78 | reg number. */ |
bc45ade3 SC |
79 | |
80 | int regno_reg_class[FIRST_PSEUDO_REGISTER] = | |
81 | { | |
8e87e161 | 82 | R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, |
bc45ade3 SC |
83 | GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, |
84 | GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, | |
85 | GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, | |
8e87e161 | 86 | GENERAL_REGS, PR_REGS, T_REGS, NO_REGS, |
2afeea0f | 87 | MAC_REGS, MAC_REGS, FPUL_REGS, GENERAL_REGS, |
1a95a963 JW |
88 | FP0_REGS,FP_REGS, FP_REGS, FP_REGS, |
89 | FP_REGS, FP_REGS, FP_REGS, FP_REGS, | |
90 | FP_REGS, FP_REGS, FP_REGS, FP_REGS, | |
91 | FP_REGS, FP_REGS, FP_REGS, FP_REGS, | |
bc45ade3 SC |
92 | }; |
93 | ||
94 | /* Provide reg_class from a letter such as appears in the machine | |
16bea517 | 95 | description. */ |
bc45ade3 SC |
96 | |
97 | enum reg_class reg_class_from_letter[] = | |
98 | { | |
99 | /* a */ NO_REGS, /* b */ NO_REGS, /* c */ NO_REGS, /* d */ NO_REGS, | |
1a95a963 | 100 | /* e */ NO_REGS, /* f */ FP_REGS, /* g */ NO_REGS, /* h */ NO_REGS, |
bc45ade3 SC |
101 | /* i */ NO_REGS, /* j */ NO_REGS, /* k */ NO_REGS, /* l */ PR_REGS, |
102 | /* m */ NO_REGS, /* n */ NO_REGS, /* o */ NO_REGS, /* p */ NO_REGS, | |
103 | /* q */ NO_REGS, /* r */ NO_REGS, /* s */ NO_REGS, /* t */ T_REGS, | |
1a95a963 JW |
104 | /* u */ NO_REGS, /* v */ NO_REGS, /* w */ FP0_REGS, /* x */ MAC_REGS, |
105 | /* y */ FPUL_REGS, /* z */ R0_REGS | |
bc45ade3 | 106 | }; |
b9654711 | 107 | \f |
16bea517 | 108 | /* Print the operand address in x to the stream. */ |
bc45ade3 SC |
109 | |
110 | void | |
111 | print_operand_address (stream, x) | |
112 | FILE *stream; | |
113 | rtx x; | |
114 | { | |
115 | switch (GET_CODE (x)) | |
116 | { | |
117 | case REG: | |
118 | fprintf (stream, "@%s", reg_names[REGNO (x)]); | |
119 | break; | |
8aa2a305 | 120 | |
bc45ade3 SC |
121 | case PLUS: |
122 | { | |
123 | rtx base = XEXP (x, 0); | |
124 | rtx index = XEXP (x, 1); | |
125 | ||
bc45ade3 SC |
126 | switch (GET_CODE (index)) |
127 | { | |
128 | case CONST_INT: | |
8aa2a305 | 129 | fprintf (stream, "@(%d,%s)", INTVAL (index), |
bc45ade3 SC |
130 | reg_names[REGNO (base)]); |
131 | break; | |
132 | ||
133 | case REG: | |
b9654711 SC |
134 | fprintf (stream, "@(r0,%s)", |
135 | reg_names[MAX (REGNO (base), REGNO (index))]); | |
bc45ade3 SC |
136 | break; |
137 | ||
138 | default: | |
b9654711 | 139 | debug_rtx (x); |
bc45ade3 SC |
140 | abort (); |
141 | } | |
142 | } | |
bc45ade3 | 143 | break; |
8aa2a305 | 144 | |
bc45ade3 SC |
145 | case PRE_DEC: |
146 | fprintf (stream, "@-%s", reg_names[REGNO (XEXP (x, 0))]); | |
147 | break; | |
148 | ||
149 | case POST_INC: | |
150 | fprintf (stream, "@%s+", reg_names[REGNO (XEXP (x, 0))]); | |
151 | break; | |
152 | ||
153 | default: | |
154 | output_addr_const (stream, x); | |
155 | break; | |
156 | } | |
157 | } | |
158 | ||
159 | /* Print operand x (an rtx) in assembler syntax to file stream | |
160 | according to modifier code. | |
161 | ||
b9654711 | 162 | '.' print a .s if insn needs delay slot |
d3ae8277 | 163 | '@' print rte or rts depending upon pragma interruptness |
8aa2a305 JW |
164 | '#' output a nop if there is nothing to put in the delay slot |
165 | 'O' print a constant without the # | |
00f8ff66 | 166 | 'R' print the LSW of a dp value - changes if in little endian |
00f8ff66 | 167 | 'S' print the MSW of a dp value - changes if in little endian |
8aa2a305 | 168 | 'T' print the next word of a dp value - same as 'R' in big endian mode. */ |
bc45ade3 SC |
169 | |
170 | void | |
171 | print_operand (stream, x, code) | |
172 | FILE *stream; | |
173 | rtx x; | |
174 | int code; | |
175 | { | |
176 | switch (code) | |
177 | { | |
b9654711 | 178 | case '.': |
79b2746a JW |
179 | if (final_sequence |
180 | && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) | |
b9654711 SC |
181 | fprintf (stream, ".s"); |
182 | break; | |
d3ae8277 SC |
183 | case '@': |
184 | if (pragma_interrupt) | |
8e87e161 | 185 | fprintf (stream, "rte"); |
d3ae8277 | 186 | else |
8e87e161 | 187 | fprintf (stream, "rts"); |
d3ae8277 | 188 | break; |
bc45ade3 | 189 | case '#': |
16bea517 | 190 | /* Output a nop if there's nothing in the delay slot. */ |
bc45ade3 | 191 | if (dbr_sequence_length () == 0) |
8aa2a305 | 192 | fprintf (stream, "\n\tnop"); |
bc45ade3 | 193 | break; |
b9654711 | 194 | case 'O': |
0d7e008e | 195 | output_addr_const (stream, x); |
bc45ade3 | 196 | break; |
bc45ade3 | 197 | case 'R': |
8aa2a305 JW |
198 | fputs (reg_names[REGNO (x) + LSW], (stream)); |
199 | break; | |
200 | case 'S': | |
201 | fputs (reg_names[REGNO (x) + MSW], (stream)); | |
00f8ff66 SC |
202 | break; |
203 | case 'T': | |
16bea517 | 204 | /* Next word of a double. */ |
bc45ade3 SC |
205 | switch (GET_CODE (x)) |
206 | { | |
207 | case REG: | |
208 | fputs (reg_names[REGNO (x) + 1], (stream)); | |
209 | break; | |
210 | case MEM: | |
8aa2a305 JW |
211 | print_operand_address (stream, |
212 | XEXP (adj_offsettable_operand (x, 4), 0)); | |
bc45ade3 SC |
213 | break; |
214 | } | |
215 | break; | |
bc45ade3 SC |
216 | default: |
217 | switch (GET_CODE (x)) | |
218 | { | |
219 | case REG: | |
220 | fputs (reg_names[REGNO (x)], (stream)); | |
221 | break; | |
222 | case MEM: | |
223 | output_address (XEXP (x, 0)); | |
224 | break; | |
225 | default: | |
226 | fputc ('#', stream); | |
227 | output_addr_const (stream, x); | |
228 | break; | |
bc45ade3 SC |
229 | } |
230 | break; | |
231 | } | |
232 | } | |
bc45ade3 | 233 | \f |
0d7e008e SC |
234 | /* Emit code to perform a block move. Choose the best method. |
235 | ||
236 | OPERANDS[0] is the destination. | |
237 | OPERANDS[1] is the source. | |
238 | OPERANDS[2] is the size. | |
239 | OPERANDS[3] is the alignment safe to use. */ | |
240 | ||
0d7e008e SC |
241 | int |
242 | expand_block_move (operands) | |
243 | rtx *operands; | |
244 | { | |
245 | int align = INTVAL (operands[3]); | |
246 | int constp = (GET_CODE (operands[2]) == CONST_INT); | |
247 | int bytes = (constp ? INTVAL (operands[2]) : 0); | |
0d7e008e | 248 | |
8aa2a305 JW |
249 | /* If it isn't a constant number of bytes, or if it doesn't have 4 byte |
250 | alignment, or if it isn't a multiple of 4 bytes, then fail. */ | |
251 | if (! constp || align < 4 || (bytes % 4 != 0)) | |
d3ae8277 SC |
252 | return 0; |
253 | ||
8aa2a305 | 254 | if (bytes < 64) |
0d7e008e SC |
255 | { |
256 | char entry[30]; | |
257 | tree entry_name; | |
258 | rtx func_addr_rtx; | |
259 | rtx r4 = gen_rtx (REG, SImode, 4); | |
260 | rtx r5 = gen_rtx (REG, SImode, 5); | |
8aa2a305 JW |
261 | |
262 | sprintf (entry, "__movstrSI%d", bytes); | |
0d7e008e SC |
263 | entry_name = get_identifier (entry); |
264 | ||
8aa2a305 JW |
265 | func_addr_rtx |
266 | = copy_to_mode_reg (Pmode, | |
267 | gen_rtx (SYMBOL_REF, Pmode, | |
268 | IDENTIFIER_POINTER (entry_name))); | |
0d7e008e SC |
269 | emit_insn (gen_move_insn (r4, XEXP (operands[0], 0))); |
270 | emit_insn (gen_move_insn (r5, XEXP (operands[1], 0))); | |
271 | emit_insn (gen_block_move_real (func_addr_rtx)); | |
272 | return 1; | |
273 | } | |
8aa2a305 JW |
274 | |
275 | /* This is the same number of bytes as a memcpy call, but to a different | |
276 | less common function name, so this will occasionally use more space. */ | |
277 | if (! TARGET_SMALLCODE) | |
0d7e008e | 278 | { |
0d7e008e SC |
279 | tree entry_name; |
280 | rtx func_addr_rtx; | |
8aa2a305 | 281 | int final_switch, while_loop; |
0d7e008e SC |
282 | rtx r4 = gen_rtx (REG, SImode, 4); |
283 | rtx r5 = gen_rtx (REG, SImode, 5); | |
284 | rtx r6 = gen_rtx (REG, SImode, 6); | |
0d7e008e | 285 | |
8aa2a305 JW |
286 | entry_name = get_identifier ("__movstr"); |
287 | func_addr_rtx | |
288 | = copy_to_mode_reg (Pmode, | |
289 | gen_rtx (SYMBOL_REF, Pmode, | |
290 | IDENTIFIER_POINTER (entry_name))); | |
0d7e008e SC |
291 | emit_insn (gen_move_insn (r4, XEXP (operands[0], 0))); |
292 | emit_insn (gen_move_insn (r5, XEXP (operands[1], 0))); | |
293 | ||
8aa2a305 JW |
294 | /* r6 controls the size of the move. 16 is decremented from it |
295 | for each 64 bytes moved. Then the negative bit left over is used | |
296 | as an index into a list of move instructions. e.g., a 72 byte move | |
297 | would be set up with size(r6) = 14, for one iteration through the | |
298 | big while loop, and a switch of -2 for the last part. */ | |
0d7e008e | 299 | |
8aa2a305 JW |
300 | final_switch = 16 - ((bytes / 4) % 16); |
301 | while_loop = ((bytes / 4) / 16 - 1) * 16; | |
302 | emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch))); | |
303 | emit_insn (gen_block_lump_real (func_addr_rtx)); | |
304 | return 1; | |
0d7e008e | 305 | } |
0d7e008e | 306 | |
d3ae8277 | 307 | return 0; |
0d7e008e SC |
308 | } |
309 | ||
bc45ade3 | 310 | /* Prepare operands for a move define_expand; specifically, one of the |
8aa2a305 | 311 | operands must be in a register. */ |
bc45ade3 | 312 | |
b9654711 | 313 | int |
bc45ade3 SC |
314 | prepare_move_operands (operands, mode) |
315 | rtx operands[]; | |
316 | enum machine_mode mode; | |
317 | { | |
e22856e8 JW |
318 | if (! reload_in_progress && ! reload_completed) |
319 | { | |
320 | /* Copy the source to a register if both operands aren't registers. */ | |
321 | if (! register_operand (operands[0], mode) | |
322 | && ! register_operand (operands[1], mode)) | |
323 | operands[1] = copy_to_mode_reg (mode, operands[1]); | |
324 | ||
325 | /* This case can happen while generating code to move the result | |
326 | of a library call to the target. Reject `st r0,@(rX,rY)' because | |
327 | reload will fail to find a spill register for rX, since r0 is already | |
328 | being used for the source. */ | |
329 | else if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 0 | |
330 | && GET_CODE (operands[0]) == MEM | |
331 | && GET_CODE (XEXP (operands[0], 0)) == PLUS | |
332 | && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == REG) | |
333 | operands[1] = copy_to_mode_reg (mode, operands[1]); | |
334 | } | |
8aa2a305 JW |
335 | |
336 | return 0; | |
337 | } | |
338 | ||
339 | /* Prepare the operands for an scc instruction; make sure that the | |
340 | compare has been done. */ | |
341 | rtx | |
342 | prepare_scc_operands (code) | |
343 | enum rtx_code code; | |
344 | { | |
345 | rtx t_reg = gen_rtx (REG, SImode, T_REG); | |
346 | enum rtx_code oldcode = code; | |
9374bd85 | 347 | enum machine_mode mode; |
8aa2a305 JW |
348 | |
349 | /* First need a compare insn. */ | |
350 | switch (code) | |
bc45ade3 | 351 | { |
8aa2a305 JW |
352 | case NE: |
353 | /* It isn't possible to handle this case. */ | |
354 | abort (); | |
355 | case LT: | |
356 | code = GT; | |
357 | break; | |
358 | case LE: | |
359 | code = GE; | |
360 | break; | |
361 | case LTU: | |
362 | code = GTU; | |
363 | break; | |
364 | case LEU: | |
365 | code = GEU; | |
366 | break; | |
bc45ade3 | 367 | } |
8aa2a305 | 368 | if (code != oldcode) |
b9654711 | 369 | { |
8aa2a305 JW |
370 | rtx tmp = sh_compare_op0; |
371 | sh_compare_op0 = sh_compare_op1; | |
372 | sh_compare_op1 = tmp; | |
0d7e008e | 373 | } |
b9654711 | 374 | |
9374bd85 RK |
375 | mode = GET_MODE (sh_compare_op0); |
376 | if (mode == VOIDmode) | |
377 | mode = GET_MODE (sh_compare_op1); | |
378 | ||
379 | sh_compare_op0 = force_reg (mode, sh_compare_op0); | |
8aa2a305 JW |
380 | if (code != EQ && code != NE |
381 | && (sh_compare_op1 != const0_rtx | |
382 | || code == GTU || code == GEU || code == LTU || code == LEU)) | |
9374bd85 | 383 | sh_compare_op1 = force_reg (mode, sh_compare_op1); |
0d7e008e | 384 | |
1a95a963 JW |
385 | /* ??? This should be `mode' not `SImode' in the compare, but that would |
386 | require fixing the branch patterns too. */ | |
8aa2a305 JW |
387 | emit_insn (gen_rtx (SET, VOIDmode, t_reg, |
388 | gen_rtx (code, SImode, sh_compare_op0, | |
389 | sh_compare_op1))); | |
0d7e008e | 390 | |
8aa2a305 | 391 | return t_reg; |
bc45ade3 SC |
392 | } |
393 | ||
8aa2a305 JW |
394 | /* Called from the md file, set up the operands of a compare instruction. */ |
395 | ||
396 | void | |
397 | from_compare (operands, code) | |
398 | rtx *operands; | |
8e87e161 | 399 | int code; |
bc45ade3 | 400 | { |
8aa2a305 | 401 | if (code != EQ && code != NE) |
bc45ade3 | 402 | { |
24a25d45 JW |
403 | enum machine_mode mode = GET_MODE (sh_compare_op0); |
404 | if (mode == VOIDmode) | |
405 | mode = GET_MODE (sh_compare_op1); | |
406 | ||
8aa2a305 | 407 | /* Force args into regs, since we can't use constants here. */ |
24a25d45 | 408 | sh_compare_op0 = force_reg (mode, sh_compare_op0); |
8aa2a305 JW |
409 | if (sh_compare_op1 != const0_rtx |
410 | || code == GTU || code == GEU || code == LTU || code == LEU) | |
24a25d45 | 411 | sh_compare_op1 = force_reg (mode, sh_compare_op1); |
bc45ade3 | 412 | } |
8aa2a305 JW |
413 | operands[1] = sh_compare_op0; |
414 | operands[2] = sh_compare_op1; | |
bc45ade3 SC |
415 | } |
416 | \f | |
16bea517 | 417 | /* Functions to output assembly code. */ |
bc45ade3 | 418 | |
b9654711 | 419 | /* Return a sequence of instructions to perform DI or DF move. |
bc45ade3 | 420 | |
b9654711 | 421 | Since the SH cannot move a DI or DF in one instruction, we have |
16bea517 | 422 | to take care when we see overlapping source and dest registers. */ |
0d7e008e | 423 | |
bc45ade3 | 424 | char * |
0d7e008e SC |
425 | output_movedouble (insn, operands, mode) |
426 | rtx insn; | |
bc45ade3 SC |
427 | rtx operands[]; |
428 | enum machine_mode mode; | |
429 | { | |
b9654711 SC |
430 | rtx dst = operands[0]; |
431 | rtx src = operands[1]; | |
b9654711 | 432 | |
0d7e008e | 433 | if (GET_CODE (dst) == MEM |
16bea517 | 434 | && GET_CODE (XEXP (dst, 0)) == PRE_DEC) |
8aa2a305 JW |
435 | return "mov.l %T1,%0\n\tmov.l %1,%0"; |
436 | ||
b9654711 SC |
437 | if (register_operand (dst, mode) |
438 | && register_operand (src, mode)) | |
bc45ade3 | 439 | { |
b9654711 | 440 | if (REGNO (src) == MACH_REG) |
00f8ff66 | 441 | return "sts mach,%S0\n\tsts macl,%R0"; |
bc45ade3 | 442 | |
8aa2a305 JW |
443 | /* When mov.d r1,r2 do r2->r3 then r1->r2; |
444 | when mov.d r1,r0 do r1->r0 then r2->r1. */ | |
b9654711 SC |
445 | |
446 | if (REGNO (src) + 1 == REGNO (dst)) | |
5325c0fa | 447 | return "mov %T1,%T0\n\tmov %1,%0"; |
b9654711 | 448 | else |
5325c0fa | 449 | return "mov %1,%0\n\tmov %T1,%T0"; |
b9654711 SC |
450 | } |
451 | else if (GET_CODE (src) == CONST_INT) | |
bc45ade3 | 452 | { |
8aa2a305 JW |
453 | if (INTVAL (src) < 0) |
454 | output_asm_insn ("mov #-1,%S0", operands); | |
bc45ade3 | 455 | else |
8aa2a305 | 456 | output_asm_insn ("mov #0,%S0", operands); |
bc45ade3 | 457 | |
8aa2a305 | 458 | return "mov %1,%R0"; |
0d7e008e | 459 | } |
b9654711 | 460 | else if (GET_CODE (src) == MEM) |
bc45ade3 | 461 | { |
8aa2a305 | 462 | int ptrreg = -1; |
b9654711 SC |
463 | int dreg = REGNO (dst); |
464 | rtx inside = XEXP (src, 0); | |
bc45ade3 SC |
465 | |
466 | if (GET_CODE (inside) == REG) | |
8aa2a305 | 467 | ptrreg = REGNO (inside); |
79b2746a JW |
468 | else if (GET_CODE (inside) == SUBREG) |
469 | ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside); | |
bc45ade3 SC |
470 | else if (GET_CODE (inside) == PLUS) |
471 | { | |
8aa2a305 JW |
472 | ptrreg = REGNO (XEXP (inside, 0)); |
473 | /* ??? A r0+REG address shouldn't be possible here, because it isn't | |
474 | an offsettable address. Unfortunately, offsettable addresses use | |
475 | QImode to check the offset, and a QImode offsettable address | |
476 | requires r0 for the other operand, which is not currently | |
477 | supported, so we can't use the 'o' constraint. | |
478 | Thus we must check for and handle r0+REG addresses here. | |
479 | We punt for now, since this is likely very rare. */ | |
480 | if (GET_CODE (XEXP (inside, 1)) == REG) | |
481 | abort (); | |
bc45ade3 | 482 | } |
0d7e008e | 483 | else if (GET_CODE (inside) == LABEL_REF) |
8aa2a305 | 484 | return "mov.l %1,%0\n\tmov.l %1+4,%T0"; |
8e87e161 | 485 | else if (GET_CODE (inside) == POST_INC) |
8aa2a305 | 486 | return "mov.l %1,%0\n\tmov.l %1,%T0"; |
bc45ade3 SC |
487 | else |
488 | abort (); | |
489 | ||
8aa2a305 JW |
490 | /* Work out the safe way to copy. Copy into the second half first. */ |
491 | if (dreg == ptrreg) | |
492 | return "mov.l %T1,%T0\n\tmov.l %1,%0"; | |
bc45ade3 SC |
493 | } |
494 | ||
00f8ff66 | 495 | return "mov.l %1,%0\n\tmov.l %T1,%T0"; |
bc45ade3 SC |
496 | } |
497 | ||
8aa2a305 JW |
498 | /* Print an instruction which would have gone into a delay slot after |
499 | another instruction, but couldn't because the other instruction expanded | |
500 | into a sequence where putting the slot insn at the end wouldn't work. */ | |
0d7e008e | 501 | |
8aa2a305 JW |
502 | static void |
503 | print_slot (insn) | |
504 | rtx insn; | |
505 | { | |
506 | final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file, optimize, 0, 1); | |
b9654711 | 507 | |
8aa2a305 JW |
508 | INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1; |
509 | } | |
0d7e008e | 510 | |
8aa2a305 JW |
511 | /* We can't tell if we need a register as a scratch for the jump |
512 | until after branch shortening, and then it's too late to allocate a | |
513 | register the 'proper' way. These instruction sequences are rare | |
514 | anyway, so to avoid always using a reg up from our limited set, we'll | |
515 | grab one when we need one on output. */ | |
0d7e008e | 516 | |
8aa2a305 JW |
517 | /* ??? Should fix compiler so that using a clobber scratch in jump |
518 | instructions works, and then this will be unnecessary. */ | |
0d7e008e SC |
519 | |
520 | char * | |
521 | output_far_jump (insn, op) | |
522 | rtx insn; | |
523 | rtx op; | |
524 | { | |
525 | rtx thislab = gen_label_rtx (); | |
526 | ||
8aa2a305 | 527 | /* Output the delay slot insn first if any. */ |
0d7e008e | 528 | if (dbr_sequence_length ()) |
8aa2a305 | 529 | print_slot (final_sequence); |
b9654711 | 530 | |
8aa2a305 JW |
531 | output_asm_insn ("mov.l r13,@-r15", 0); |
532 | output_asm_insn ("mov.l %O0,r13", &thislab); | |
533 | output_asm_insn ("jmp @r13", 0); | |
534 | output_asm_insn ("mov.l @r15+,r13", 0); | |
0d7e008e | 535 | output_asm_insn (".align 2", 0); |
d3ae8277 | 536 | ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (thislab)); |
0d7e008e SC |
537 | output_asm_insn (".long %O0", &op); |
538 | return ""; | |
539 | } | |
bc45ade3 | 540 | |
8aa2a305 JW |
541 | /* Local label counter, used for constants in the pool and inside |
542 | pattern branches. */ | |
543 | ||
544 | static int lf = 100; | |
545 | ||
546 | /* Output code for ordinary branches. */ | |
547 | ||
bc45ade3 | 548 | char * |
8aa2a305 | 549 | output_branch (logic, insn, operands) |
bc45ade3 | 550 | int logic; |
b9654711 | 551 | rtx insn; |
8aa2a305 | 552 | rtx *operands; |
bc45ade3 | 553 | { |
bc45ade3 | 554 | int label = lf++; |
e4fa6b06 ILT |
555 | int length = get_attr_length (insn); |
556 | int adjusted_length; | |
8e87e161 | 557 | |
e4fa6b06 | 558 | /* Undo the effects of ADJUST_INSN_LENGTH, so that we get the real |
9c0e838f ILT |
559 | length. If NEXT_INSN (PREV_INSN (insn)) != insn, then the insn |
560 | is inside a sequence, and ADJUST_INSN_LENGTH was not called on | |
561 | it. */ | |
562 | if (PREV_INSN (insn) == NULL | |
563 | || NEXT_INSN (PREV_INSN (insn)) == insn) | |
564 | { | |
565 | adjusted_length = length; | |
566 | ADJUST_INSN_LENGTH (insn, adjusted_length); | |
567 | length -= (adjusted_length - length); | |
568 | } | |
e4fa6b06 ILT |
569 | |
570 | switch (length) | |
bc45ade3 SC |
571 | { |
572 | case 2: | |
22e1ebf1 JW |
573 | /* A branch with an unfilled delay slot. */ |
574 | case 4: | |
575 | /* Simple branch in range -252..+258 bytes */ | |
b9654711 | 576 | return logic ? "bt%. %l0" : "bf%. %l0"; |
bc45ade3 SC |
577 | |
578 | case 6: | |
22e1ebf1 JW |
579 | /* A branch with an unfilled delay slot. */ |
580 | case 8: | |
16bea517 | 581 | /* Branch in range -4092..+4098 bytes. */ |
b9654711 | 582 | { |
8aa2a305 JW |
583 | /* The call to print_slot will clobber the operands. */ |
584 | rtx op0 = operands[0]; | |
b9654711 | 585 | |
79b2746a JW |
586 | /* If the instruction in the delay slot is annulled (true), then |
587 | there is no delay slot where we can put it now. The only safe | |
588 | place for it is after the label. */ | |
589 | ||
16bea517 | 590 | if (final_sequence) |
b9654711 | 591 | { |
79b2746a JW |
592 | fprintf (asm_out_file, "\tb%c%s\tLF%d\n", logic ? 'f' : 't', |
593 | INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)) | |
594 | ? "" : ".s", label); | |
595 | if (! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) | |
596 | print_slot (final_sequence); | |
b9654711 | 597 | } |
b9654711 | 598 | else |
8aa2a305 | 599 | fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label); |
b9654711 | 600 | |
8aa2a305 JW |
601 | output_asm_insn ("bra %l0", &op0); |
602 | fprintf (asm_out_file, "\tnop\n"); | |
b9654711 | 603 | fprintf (asm_out_file, "LF%d:\n", label); |
79b2746a JW |
604 | |
605 | if (final_sequence | |
606 | && INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) | |
607 | print_slot (final_sequence); | |
b9654711 | 608 | } |
bc45ade3 SC |
609 | return ""; |
610 | ||
8aa2a305 JW |
611 | case 16: |
612 | /* A branch with an unfilled delay slot. */ | |
613 | case 18: | |
614 | /* Branches a long way away. */ | |
615 | { | |
616 | /* The call to print_slot will clobber the operands. */ | |
617 | rtx op0 = operands[0]; | |
bc45ade3 | 618 | |
79b2746a JW |
619 | /* If the instruction in the delay slot is annulled (true), then |
620 | there is no delay slot where we can put it now. The only safe | |
621 | place for it is after the label. */ | |
622 | ||
8aa2a305 JW |
623 | if (final_sequence) |
624 | { | |
79b2746a JW |
625 | fprintf (asm_out_file, "\tb%c%s\tLF%d\n", logic ? 'f' : 't', |
626 | INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)) | |
627 | ? "" : ".s", label); | |
628 | if (! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) | |
629 | print_slot (final_sequence); | |
8aa2a305 JW |
630 | } |
631 | else | |
632 | fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label); | |
bc45ade3 | 633 | |
8aa2a305 JW |
634 | output_far_jump (insn, op0); |
635 | fprintf (asm_out_file, "LF%d:\n", label); | |
79b2746a JW |
636 | |
637 | if (final_sequence | |
638 | && INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) | |
639 | print_slot (final_sequence); | |
8aa2a305 | 640 | } |
79b2746a | 641 | return ""; |
bc45ade3 | 642 | } |
e4fa6b06 ILT |
643 | |
644 | abort (); | |
bc45ade3 | 645 | } |
8e87e161 | 646 | \f |
8aa2a305 JW |
647 | /* Output to FILE the start of the assembler file. */ |
648 | ||
0d7e008e | 649 | void |
adade868 | 650 | output_file_start (file) |
0d7e008e | 651 | FILE *file; |
bc45ade3 | 652 | { |
0d7e008e | 653 | register int pos; |
b9654711 | 654 | |
0d7e008e | 655 | output_file_directive (file, main_input_filename); |
b9654711 | 656 | |
0d7e008e SC |
657 | /* Switch to the data section so that the coffsem symbol and the |
658 | gcc2_compiled. symbol aren't in the text section. */ | |
659 | data_section (); | |
b9654711 | 660 | |
8aa2a305 JW |
661 | if (TARGET_LITTLE_ENDIAN) |
662 | fprintf (file, "\t.little\n"); | |
bc45ade3 | 663 | } |
0d7e008e | 664 | \f |
16bea517 | 665 | /* Actual number of instructions used to make a shift by N. */ |
8aa2a305 | 666 | static char ashiftrt_insns[] = |
16bea517 JW |
667 | { 0,1,2,3,4,5,8,8,8,8,8,8,8,8,8,8,2,3,4,5,8,8,8,8,8,8,8,8,8,8,8,2}; |
668 | ||
669 | /* Left shift and logical right shift are the same. */ | |
8aa2a305 | 670 | static char shift_insns[] = |
16bea517 | 671 | { 0,1,1,2,2,3,3,4,1,2,2,3,3,4,3,3,1,2,2,3,3,4,3,3,2,3,3,4,4,4,3,3}; |
8aa2a305 | 672 | |
16bea517 JW |
673 | /* Individual shift amounts needed to get the above length sequences. |
674 | One bit right shifts clobber the T bit, so when possible, put one bit | |
675 | shifts in the middle of the sequence, so the ends are eligible for | |
676 | branch delay slots. */ | |
8aa2a305 | 677 | static short shift_amounts[32][5] = { |
16bea517 JW |
678 | {0}, {1}, {2}, {2, 1}, |
679 | {2, 2}, {2, 1, 2}, {2, 2, 2}, {2, 2, 1, 2}, | |
680 | {8}, {8, 1}, {8, 2}, {8, 1, 2}, | |
681 | {8, 2, 2}, {8, 2, 1, 2}, {8, -2, 8}, {8, -1, 8}, | |
682 | {16}, {16, 1}, {16, 2}, {16, 1, 2}, | |
683 | {16, 2, 2}, {16, 2, 1, 2}, {16, -2, 8}, {16, -1, 8}, | |
684 | {16, 8}, {16, 1, 8}, {16, 8, 2}, {16, 8, 1, 2}, | |
1d3534c0 | 685 | {16, 8, 2, 2}, {16, -1, -2, 16}, {16, -2, 16}, {16, -1, 16}}; |
16bea517 | 686 | |
8d481241 JW |
687 | /* Likewise, but for shift amounts < 16, up to three highmost bits |
688 | might be clobbered. This is typically used when combined with some | |
689 | kind of sign or zero extension. */ | |
690 | ||
691 | static char ext_shift_insns[] = | |
692 | { 0,1,1,2,2,3,2,2,1,2,2,3,3,3,2,2,1,2,2,3,3,4,3,3,2,3,3,4,4,4,3,3}; | |
693 | ||
694 | static short ext_shift_amounts[32][4] = { | |
695 | {0}, {1}, {2}, {2, 1}, | |
696 | {2, 2}, {2, 1, 2}, {8, -2}, {8, -1}, | |
697 | {8}, {8, 1}, {8, 2}, {8, 1, 2}, | |
698 | {8, 2, 2}, {16, -2, -1}, {16, -2}, {16, -1}, | |
699 | {16}, {16, 1}, {16, 2}, {16, 1, 2}, | |
700 | {16, 2, 2}, {16, 2, 1, 2}, {16, -2, 8}, {16, -1, 8}, | |
701 | {16, 8}, {16, 1, 8}, {16, 8, 2}, {16, 8, 1, 2}, | |
702 | {16, 8, 2, 2}, {16, -1, -2, 16}, {16, -2, 16}, {16, -1, 16}}; | |
703 | ||
ae9d19c0 JR |
704 | /* Assuming we have a value that has been sign-extended by at least one bit, |
705 | can we use the ext_shift_amounts with the last shift turned to an arithmetic shift | |
706 | to shift it by N without data loss, and quicker than by other means? */ | |
707 | #define EXT_SHIFT_SIGNED(n) (((n) | 8) == 15) | |
708 | ||
16bea517 JW |
709 | /* This is used in length attributes in sh.md to help compute the length |
710 | of arbitrary constant shift instructions. */ | |
bc45ade3 | 711 | |
16bea517 JW |
712 | int |
713 | shift_insns_rtx (insn) | |
714 | rtx insn; | |
715 | { | |
716 | rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); | |
717 | int shift_count = INTVAL (XEXP (set_src, 1)); | |
718 | enum rtx_code shift_code = GET_CODE (set_src); | |
00f8ff66 | 719 | |
16bea517 JW |
720 | switch (shift_code) |
721 | { | |
722 | case ASHIFTRT: | |
723 | return ashiftrt_insns[shift_count]; | |
724 | case LSHIFTRT: | |
725 | case ASHIFT: | |
726 | return shift_insns[shift_count]; | |
727 | default: | |
728 | abort(); | |
729 | } | |
730 | } | |
731 | ||
16bea517 | 732 | /* Return the cost of a shift. */ |
bc45ade3 | 733 | |
0d7e008e | 734 | int |
8aa2a305 JW |
735 | shiftcosts (x) |
736 | rtx x; | |
bc45ade3 | 737 | { |
8aa2a305 JW |
738 | int value = INTVAL (XEXP (x, 1)); |
739 | ||
16bea517 | 740 | /* If shift by a non constant, then this will be expensive. */ |
8aa2a305 | 741 | if (GET_CODE (XEXP (x, 1)) != CONST_INT) |
00f8ff66 | 742 | { |
20b04867 JW |
743 | if (TARGET_SH3) |
744 | return 2; | |
745 | /* If not an sh3 then we don't even have an instruction for it. */ | |
00f8ff66 SC |
746 | return 20; |
747 | } | |
bc45ade3 | 748 | |
16bea517 | 749 | /* Otherwise, return the true cost in instructions. */ |
8aa2a305 | 750 | if (GET_CODE (x) == ASHIFTRT) |
49b6d06b JW |
751 | { |
752 | int cost = ashiftrt_insns[value]; | |
753 | /* If SH3, then we put the constant in a reg and use shad. */ | |
754 | if (TARGET_SH3 && cost > 3) | |
755 | cost = 3; | |
756 | return cost; | |
757 | } | |
8aa2a305 JW |
758 | else |
759 | return shift_insns[value]; | |
0d7e008e | 760 | } |
b9654711 | 761 | |
8aa2a305 JW |
762 | /* Return the cost of an AND operation. */ |
763 | ||
8e87e161 | 764 | int |
8aa2a305 JW |
765 | andcosts (x) |
766 | rtx x; | |
0d7e008e SC |
767 | { |
768 | int i; | |
8aa2a305 | 769 | |
a6f71af5 | 770 | /* Anding with a register is a single cycle and instruction. */ |
8aa2a305 | 771 | if (GET_CODE (XEXP (x, 1)) != CONST_INT) |
a6f71af5 | 772 | return 1; |
8aa2a305 JW |
773 | |
774 | i = INTVAL (XEXP (x, 1)); | |
a6f71af5 | 775 | /* These constants are single cycle extu.[bw] instructions. */ |
0d7e008e | 776 | if (i == 0xff || i == 0xffff) |
a6f71af5 JW |
777 | return 1; |
778 | /* Constants that can be used in an and immediate instruction is a single | |
779 | cycle, but this requires r0, so make it a little more expensive. */ | |
780 | if (CONST_OK_FOR_L (i)) | |
0d7e008e | 781 | return 2; |
a6f71af5 JW |
782 | /* Constants that can be loaded with a mov immediate and an and. |
783 | This case is probably unnecessary. */ | |
0d7e008e | 784 | if (CONST_OK_FOR_I (i)) |
a6f71af5 JW |
785 | return 2; |
786 | /* Any other constants requires a 2 cycle pc-relative load plus an and. | |
787 | This case is probably unnecessary. */ | |
788 | return 3; | |
0d7e008e | 789 | } |
d3ae8277 | 790 | |
16bea517 | 791 | /* Return the cost of a multiply. */ |
0d7e008e | 792 | int |
8aa2a305 JW |
793 | multcosts (x) |
794 | rtx x; | |
0d7e008e SC |
795 | { |
796 | if (TARGET_SH2) | |
d3ae8277 SC |
797 | { |
798 | /* We have a mul insn, so we can never take more than the mul and the | |
a7771f78 | 799 | read of the mac reg, but count more because of the latency and extra |
16bea517 | 800 | reg usage. */ |
d3ae8277 | 801 | if (TARGET_SMALLCODE) |
8e87e161 | 802 | return 2; |
a7771f78 | 803 | return 3; |
d3ae8277 SC |
804 | } |
805 | ||
a7771f78 | 806 | /* If we're aiming at small code, then just count the number of |
16bea517 | 807 | insns in a multiply call sequence. */ |
8e87e161 | 808 | if (TARGET_SMALLCODE) |
8aa2a305 | 809 | return 5; |
d3ae8277 | 810 | |
16bea517 | 811 | /* Otherwise count all the insns in the routine we'd be calling too. */ |
d3ae8277 | 812 | return 20; |
0d7e008e | 813 | } |
b9654711 | 814 | |
16bea517 | 815 | /* Code to expand a shift. */ |
b9654711 | 816 | |
0d7e008e SC |
817 | void |
818 | gen_ashift (type, n, reg) | |
819 | int type; | |
820 | int n; | |
821 | rtx reg; | |
822 | { | |
16bea517 JW |
823 | /* Negative values here come from the shift_amounts array. */ |
824 | if (n < 0) | |
825 | { | |
826 | if (type == ASHIFT) | |
827 | type = LSHIFTRT; | |
828 | else | |
829 | type = ASHIFT; | |
830 | n = -n; | |
831 | } | |
832 | ||
0d7e008e | 833 | switch (type) |
bc45ade3 | 834 | { |
0d7e008e SC |
835 | case ASHIFTRT: |
836 | emit_insn (gen_ashrsi3_k (reg, reg, GEN_INT (n))); | |
837 | break; | |
838 | case LSHIFTRT: | |
16bea517 JW |
839 | if (n == 1) |
840 | emit_insn (gen_lshrsi3_m (reg, reg, GEN_INT (n))); | |
841 | else | |
842 | emit_insn (gen_lshrsi3_k (reg, reg, GEN_INT (n))); | |
0d7e008e SC |
843 | break; |
844 | case ASHIFT: | |
5325c0fa | 845 | emit_insn (gen_ashlsi3_k (reg, reg, GEN_INT (n))); |
0d7e008e | 846 | break; |
bc45ade3 | 847 | } |
bc45ade3 | 848 | } |
bc45ade3 | 849 | |
8d481241 JW |
850 | /* Same for HImode */ |
851 | ||
852 | void | |
853 | gen_ashift_hi (type, n, reg) | |
854 | int type; | |
855 | int n; | |
856 | rtx reg; | |
857 | { | |
858 | /* Negative values here come from the shift_amounts array. */ | |
859 | if (n < 0) | |
860 | { | |
861 | if (type == ASHIFT) | |
862 | type = LSHIFTRT; | |
863 | else | |
864 | type = ASHIFT; | |
865 | n = -n; | |
866 | } | |
867 | ||
868 | switch (type) | |
869 | { | |
870 | case ASHIFTRT: | |
871 | emit_insn (gen_ashrhi3_k (reg, reg, GEN_INT (n))); | |
872 | break; | |
873 | case LSHIFTRT: | |
874 | if (n == 1) | |
875 | emit_insn (gen_lshrhi3_m (reg, reg, GEN_INT (n))); | |
876 | else | |
877 | emit_insn (gen_lshrhi3_k (reg, reg, GEN_INT (n))); | |
878 | break; | |
879 | case ASHIFT: | |
880 | emit_insn (gen_ashlhi3_k (reg, reg, GEN_INT (n))); | |
881 | break; | |
882 | } | |
883 | } | |
884 | ||
8aa2a305 JW |
885 | /* Output RTL to split a constant shift into its component SH constant |
886 | shift instructions. */ | |
887 | ||
0d7e008e SC |
888 | int |
889 | gen_shifty_op (code, operands) | |
890 | int code; | |
891 | rtx *operands; | |
bc45ade3 | 892 | { |
16bea517 | 893 | int value = INTVAL (operands[2]); |
8aa2a305 | 894 | int max, i; |
00f8ff66 | 895 | |
cff3d762 JW |
896 | /* Truncate the shift count in case it is out of bounds. */ |
897 | value = value & 0x1f; | |
898 | ||
8aa2a305 | 899 | if (value == 31) |
16bea517 | 900 | { |
8aa2a305 | 901 | if (code == LSHIFTRT) |
0d7e008e | 902 | { |
8aa2a305 JW |
903 | emit_insn (gen_rotlsi3_1 (operands[0], operands[0])); |
904 | emit_insn (gen_movt (operands[0])); | |
905 | return; | |
16bea517 | 906 | } |
8aa2a305 | 907 | else if (code == ASHIFT) |
16bea517 | 908 | { |
8aa2a305 JW |
909 | /* There is a two instruction sequence for 31 bit left shifts, |
910 | but it requires r0. */ | |
911 | if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 0) | |
0d7e008e | 912 | { |
8aa2a305 JW |
913 | emit_insn (gen_andsi3 (operands[0], operands[0], const1_rtx)); |
914 | emit_insn (gen_rotlsi3_31 (operands[0], operands[0])); | |
915 | return; | |
0d7e008e | 916 | } |
16bea517 | 917 | } |
8aa2a305 | 918 | } |
c17f53a8 JW |
919 | else if (value == 0) |
920 | { | |
921 | /* This can happen when not optimizing. We must output something here | |
922 | to prevent the compiler from aborting in final.c after the try_split | |
923 | call. */ | |
924 | emit_insn (gen_nop ()); | |
925 | return; | |
926 | } | |
a9f71ad8 | 927 | |
8aa2a305 JW |
928 | max = shift_insns[value]; |
929 | for (i = 0; i < max; i++) | |
930 | gen_ashift (code, shift_amounts[value][i], operands[0]); | |
931 | } | |
8d481241 JW |
932 | |
933 | /* Same as above, but optimized for values where the topmost bits don't | |
934 | matter. */ | |
935 | ||
936 | int | |
937 | gen_shifty_hi_op (code, operands) | |
938 | int code; | |
939 | rtx *operands; | |
940 | { | |
941 | int value = INTVAL (operands[2]); | |
942 | int max, i; | |
943 | void (*gen_fun)(); | |
944 | ||
945 | /* This operation is used by and_shl for SImode values with a few | |
946 | high bits known to be cleared. */ | |
947 | value &= 31; | |
948 | if (value == 0) | |
949 | { | |
950 | emit_insn (gen_nop ()); | |
951 | return; | |
952 | } | |
953 | ||
954 | gen_fun = GET_MODE (operands[0]) == HImode ? gen_ashift_hi : gen_ashift; | |
955 | if (code == ASHIFT) | |
956 | { | |
957 | max = ext_shift_insns[value]; | |
958 | for (i = 0; i < max; i++) | |
959 | gen_fun (code, ext_shift_amounts[value][i], operands[0]); | |
960 | } | |
961 | else | |
962 | /* When shifting right, emit the shifts in reverse order, so that | |
963 | solitary negative values come first. */ | |
964 | for (i = ext_shift_insns[value] - 1; i >= 0; i--) | |
965 | gen_fun (code, ext_shift_amounts[value][i], operands[0]); | |
966 | } | |
8aa2a305 JW |
967 | |
968 | /* Output RTL for an arithmetic right shift. */ | |
969 | ||
970 | /* ??? Rewrite to use super-optimizer sequences. */ | |
971 | ||
972 | int | |
973 | expand_ashiftrt (operands) | |
974 | rtx *operands; | |
975 | { | |
976 | rtx wrk; | |
977 | char func[18]; | |
978 | tree func_name; | |
979 | int value; | |
980 | ||
49b6d06b | 981 | if (TARGET_SH3) |
20b04867 | 982 | { |
49b6d06b JW |
983 | if (GET_CODE (operands[2]) != CONST_INT) |
984 | { | |
985 | rtx count = copy_to_mode_reg (SImode, operands[2]); | |
986 | emit_insn (gen_negsi2 (count, count)); | |
987 | emit_insn (gen_ashrsi3_d (operands[0], operands[1], count)); | |
988 | return 1; | |
989 | } | |
990 | else if (ashiftrt_insns[INTVAL (operands[2])] > 3) | |
991 | { | |
992 | rtx count = force_reg (SImode, GEN_INT (- INTVAL (operands[2]))); | |
993 | emit_insn (gen_ashrsi3_d (operands[0], operands[1], count)); | |
994 | return 1; | |
995 | } | |
20b04867 | 996 | } |
8aa2a305 JW |
997 | if (GET_CODE (operands[2]) != CONST_INT) |
998 | return 0; | |
999 | ||
1000 | value = INTVAL (operands[2]); | |
1001 | ||
1002 | if (value == 31) | |
1003 | { | |
1004 | emit_insn (gen_ashrsi2_31 (operands[0], operands[1])); | |
1005 | return 1; | |
1006 | } | |
1007 | else if (value >= 16 && value <= 19) | |
1008 | { | |
1009 | wrk = gen_reg_rtx (SImode); | |
1010 | emit_insn (gen_ashrsi2_16 (wrk, operands[1])); | |
1011 | value -= 16; | |
1012 | while (value--) | |
1013 | gen_ashift (ASHIFTRT, 1, wrk); | |
1014 | emit_move_insn (operands[0], wrk); | |
1015 | return 1; | |
a9f71ad8 | 1016 | } |
8aa2a305 JW |
1017 | /* Expand a short sequence inline, longer call a magic routine. */ |
1018 | else if (value <= 5) | |
1019 | { | |
1020 | wrk = gen_reg_rtx (SImode); | |
1021 | emit_move_insn (wrk, operands[1]); | |
1022 | while (value--) | |
1023 | gen_ashift (ASHIFTRT, 1, wrk); | |
1024 | emit_move_insn (operands[0], wrk); | |
1025 | return 1; | |
1026 | } | |
1027 | ||
1028 | wrk = gen_reg_rtx (Pmode); | |
1029 | ||
1030 | /* Load the value into an arg reg and call a helper. */ | |
1031 | emit_move_insn (gen_rtx (REG, SImode, 4), operands[1]); | |
1032 | sprintf (func, "__ashiftrt_r4_%d", value); | |
1033 | func_name = get_identifier (func); | |
1034 | emit_move_insn (wrk, gen_rtx (SYMBOL_REF, Pmode, | |
1035 | IDENTIFIER_POINTER (func_name))); | |
1036 | emit_insn (gen_ashrsi3_n (GEN_INT (value), wrk)); | |
1037 | emit_move_insn (operands[0], gen_rtx (REG, SImode, 4)); | |
1038 | return 1; | |
bc45ade3 | 1039 | } |
8d481241 JW |
1040 | |
1041 | /* Try to find a good way to implement the combiner pattern | |
1042 | [(set (match_operand:SI 0 "register_operand" "r") | |
1043 | (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") | |
1044 | (match_operand:SI 2 "const_int_operand" "n")) | |
1045 | (match_operand:SI 3 "const_int_operand" "n"))) . | |
1046 | LEFT_RTX is operand 2 in the above pattern, and MASK_RTX is operand 3. | |
1047 | return 0 for simple right / left or left/right shift combination. | |
1048 | return 1 for a combination of shifts with zero_extend. | |
1049 | return 2 for a combination of shifts with an AND that needs r0. | |
1050 | return 3 for a combination of shifts with an AND that needs an extra | |
1051 | scratch register, when the three highmost bits of the AND mask are clear. | |
1052 | return 4 for a combination of shifts with an AND that needs an extra | |
1053 | scratch register, when any of the three highmost bits of the AND mask | |
1054 | is set. | |
1055 | If ATTRP is set, store an initial right shift width in ATTRP[0], | |
1056 | and the instruction length in ATTRP[1] . These values are not valid | |
1057 | when returning 0. | |
1058 | When ATTRP is set and returning 1, ATTRP[2] gets set to the index into | |
1059 | shift_amounts for the last shift value that is to be used before the | |
1060 | sign extend. */ | |
1061 | int | |
1062 | shl_and_kind (left_rtx, mask_rtx, attrp) | |
1063 | rtx left_rtx, mask_rtx; | |
1064 | int *attrp; | |
1065 | { | |
1066 | unsigned HOST_WIDE_INT mask, lsb, mask2, lsb2; | |
1067 | int left = INTVAL (left_rtx), right; | |
1068 | int best = 0; | |
1069 | int cost, best_cost = 10000; | |
1070 | int best_right = 0, best_len = 0; | |
1071 | int i; | |
1072 | int can_ext; | |
1073 | ||
1074 | if (left < 0 || left > 31) | |
1075 | return 0; | |
1076 | if (GET_CODE (mask_rtx) == CONST_INT) | |
1077 | mask = (unsigned HOST_WIDE_INT) INTVAL (mask_rtx) >> left; | |
1078 | else | |
1079 | mask = (unsigned HOST_WIDE_INT) GET_MODE_MASK (SImode) >> left; | |
1080 | /* Can this be expressed as a right shift / left shift pair ? */ | |
1081 | lsb = ((mask ^ (mask - 1)) >> 1) + 1; | |
1082 | right = exact_log2 (lsb); | |
1083 | mask2 = ~(mask + lsb - 1); | |
1084 | lsb2 = ((mask2 ^ (mask2 - 1)) >> 1) + 1; | |
1085 | /* mask has no zeroes but trailing zeroes <==> ! mask2 */ | |
1086 | if (! mask2) | |
1087 | best_cost = shift_insns[right] + shift_insns[right + left]; | |
1088 | /* mask has no trailing zeroes <==> ! right */ | |
1089 | else if (! right && mask2 == ~(lsb2 - 1)) | |
1090 | { | |
1091 | int late_right = exact_log2 (lsb2); | |
1092 | best_cost = shift_insns[left + late_right] + shift_insns[late_right]; | |
1093 | } | |
1094 | /* Try to use zero extend */ | |
1095 | if (mask2 == ~(lsb2 - 1)) | |
1096 | { | |
1097 | int width, first; | |
1098 | ||
1099 | for (width = 8; width <= 16; width += 8) | |
1100 | { | |
1101 | /* Can we zero-extend right away? */ | |
1102 | if (lsb2 == (HOST_WIDE_INT)1 << width) | |
1103 | { | |
1104 | cost | |
1105 | = 1 + ext_shift_insns[right] + ext_shift_insns[left + right]; | |
1106 | if (cost < best_cost) | |
1107 | { | |
1108 | best = 1; | |
1109 | best_cost = cost; | |
1110 | best_right = right; | |
1111 | best_len = cost; | |
1112 | if (attrp) | |
1113 | attrp[2] = -1; | |
1114 | } | |
1115 | continue; | |
1116 | } | |
1117 | /* ??? Could try to put zero extend into initial right shift, | |
1118 | or even shift a bit left before the right shift. */ | |
1119 | /* Determine value of first part of left shift, to get to the | |
1120 | zero extend cut-off point. */ | |
1121 | first = width - exact_log2 (lsb2) + right; | |
1122 | if (first >= 0 && right + left - first >= 0) | |
1123 | { | |
1124 | cost = ext_shift_insns[right] + ext_shift_insns[first] + 1 | |
1125 | + ext_shift_insns[right + left - first]; | |
1126 | if (cost < best_cost) | |
1127 | { | |
1128 | best = 1; | |
1129 | best_cost = cost; | |
1130 | best_right = right; | |
1131 | best_len = cost; | |
1132 | if (attrp) | |
1133 | attrp[2] = first; | |
1134 | } | |
1135 | } | |
1136 | } | |
1137 | } | |
1138 | /* Try to use r0 AND pattern */ | |
1139 | for (i = 0; i <= 2; i++) | |
1140 | { | |
1141 | if (i > right) | |
1142 | break; | |
1143 | if (! CONST_OK_FOR_L (mask >> i)) | |
1144 | continue; | |
1145 | cost = (i != 0) + 2 + ext_shift_insns[left + i]; | |
1146 | if (cost < best_cost) | |
1147 | { | |
1148 | best = 2; | |
1149 | best_cost = cost; | |
1150 | best_right = i; | |
1151 | best_len = cost - 1; | |
1152 | } | |
1153 | } | |
1154 | /* Try to use a scratch register to hold the AND operand. */ | |
1155 | can_ext = ((mask << left) & 0xe0000000) == 0; | |
1156 | for (i = 0; i <= 2; i++) | |
1157 | { | |
1158 | if (i > right) | |
1159 | break; | |
1160 | cost = (i != 0) + (CONST_OK_FOR_I (mask >> i) ? 2 : 3) | |
1161 | + (can_ext ? ext_shift_insns : shift_insns)[left]; | |
1162 | if (cost < best_cost) | |
1163 | { | |
1164 | best = 4 - can_ext; | |
1165 | best_cost = cost; | |
1166 | best_right = i; | |
1167 | best_len = cost - 1 - ! CONST_OK_FOR_I (mask >> i); | |
1168 | } | |
1169 | } | |
1170 | ||
1171 | if (attrp) | |
1172 | { | |
1173 | attrp[0] = best_right; | |
1174 | attrp[1] = best_len; | |
1175 | } | |
1176 | return best; | |
1177 | } | |
1178 | ||
1179 | /* This is used in length attributes of the unnamed instructions | |
1180 | corresponding to shl_and_kind return values of 1 and 2. */ | |
1181 | int | |
1182 | shl_and_length (insn) | |
1183 | rtx insn; | |
1184 | { | |
1185 | rtx set_src, left_rtx, mask_rtx; | |
1186 | int attributes[3]; | |
1187 | ||
1188 | set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); | |
1189 | left_rtx = XEXP (XEXP (set_src, 0), 1); | |
1190 | mask_rtx = XEXP (set_src, 1); | |
1191 | shl_and_kind (left_rtx, mask_rtx, attributes); | |
1192 | return attributes[1]; | |
1193 | } | |
1194 | ||
1195 | /* This is used in length attribute of the and_shl_scratch instruction. */ | |
1196 | ||
1197 | int | |
1198 | shl_and_scr_length (insn) | |
1199 | rtx insn; | |
1200 | { | |
1201 | rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); | |
1202 | int len = shift_insns[INTVAL (XEXP (set_src, 1))]; | |
1203 | rtx op = XEXP (set_src, 0); | |
1204 | len += shift_insns[INTVAL (XEXP (op, 1))] + 1; | |
1205 | op = XEXP (XEXP (op, 0), 0); | |
1206 | return len + shift_insns[INTVAL (XEXP (op, 1))]; | |
1207 | } | |
1208 | ||
1209 | /* Generating rtl? */ | |
1210 | extern int rtx_equal_function_value_matters; | |
1211 | ||
1212 | /* Generate rtl for instructions for which shl_and_kind advised a particular | |
1213 | method of generating them, i.e. returned zero. */ | |
1214 | ||
1215 | int | |
1216 | gen_shl_and (dest, left_rtx, mask_rtx, source) | |
1217 | rtx dest, left_rtx, mask_rtx, source; | |
1218 | { | |
1219 | int attributes[3]; | |
1220 | unsigned HOST_WIDE_INT mask; | |
1221 | int kind = shl_and_kind (left_rtx, mask_rtx, attributes); | |
1222 | int right, total_shift; | |
1223 | int (*shift_gen_fun) PROTO((int, rtx*)) = gen_shifty_hi_op; | |
1224 | ||
1225 | right = attributes[0]; | |
1226 | total_shift = INTVAL (left_rtx) + right; | |
1227 | mask = (unsigned HOST_WIDE_INT) INTVAL (mask_rtx) >> total_shift; | |
1228 | switch (kind) | |
1229 | { | |
1230 | default: | |
1231 | return -1; | |
1232 | case 1: | |
1233 | { | |
1234 | int first = attributes[2]; | |
1235 | rtx operands[3]; | |
1236 | ||
1237 | if (first < 0) | |
1238 | { | |
1239 | emit_insn ((mask << right) == 0xff | |
afad3d2c JW |
1240 | ? gen_zero_extendqisi2(dest, |
1241 | gen_lowpart (QImode, source)) | |
1242 | : gen_zero_extendhisi2(dest, | |
1243 | gen_lowpart (HImode, source))); | |
8d481241 JW |
1244 | source = dest; |
1245 | } | |
1246 | if (source != dest) | |
1247 | emit_insn (gen_movsi (dest, source)); | |
1248 | operands[0] = dest; | |
1249 | if (right) | |
1250 | { | |
1251 | operands[2] = GEN_INT (right); | |
1252 | gen_shifty_hi_op (LSHIFTRT, operands); | |
1253 | } | |
1254 | if (first > 0) | |
1255 | { | |
1256 | operands[2] = GEN_INT (first); | |
1257 | gen_shifty_hi_op (ASHIFT, operands); | |
1258 | total_shift -= first; | |
1259 | mask <<= first; | |
1260 | } | |
1261 | if (first >= 0) | |
1262 | emit_insn (mask == 0xff | |
afad3d2c JW |
1263 | ? gen_zero_extendqisi2(dest, gen_lowpart (QImode, dest)) |
1264 | : gen_zero_extendhisi2(dest, gen_lowpart (HImode, dest))); | |
8d481241 JW |
1265 | if (total_shift > 0) |
1266 | { | |
1267 | operands[2] = GEN_INT (total_shift); | |
1268 | gen_shifty_hi_op (ASHIFT, operands); | |
1269 | } | |
1270 | break; | |
1271 | } | |
1272 | case 4: | |
1273 | shift_gen_fun = gen_shifty_op; | |
1274 | case 2: | |
1275 | case 3: | |
24c50999 JR |
1276 | /* If the topmost bit that matters is set, set the topmost bits |
1277 | that don't matter. This way, we might be able to get a shorter | |
1278 | signed constant. */ | |
1279 | if (mask & ((HOST_WIDE_INT)1 << 31 - total_shift)) | |
1280 | mask |= (HOST_WIDE_INT)~0 << (31 - total_shift); | |
8d481241 JW |
1281 | /* Don't expand fine-grained when combining, because that will |
1282 | make the pattern fail. */ | |
1283 | if (rtx_equal_function_value_matters | |
1284 | || reload_in_progress || reload_completed) | |
1285 | { | |
1286 | rtx operands[3]; | |
1287 | ||
1288 | if (right) | |
1289 | { | |
1290 | emit_insn (gen_lshrsi3 (dest, source, GEN_INT (right))); | |
1291 | source = dest; | |
1292 | } | |
1293 | emit_insn (gen_andsi3 (dest, source, GEN_INT (mask))); | |
afad3d2c JW |
1294 | if (total_shift) |
1295 | { | |
1296 | operands[0] = dest; | |
1297 | operands[1] = dest; | |
1298 | operands[2] = GEN_INT (total_shift); | |
1299 | shift_gen_fun (ASHIFT, operands); | |
1300 | } | |
8d481241 JW |
1301 | break; |
1302 | } | |
1303 | else | |
1304 | { | |
1305 | int neg = 0; | |
1306 | if (kind != 4 && total_shift < 16) | |
1307 | { | |
1308 | neg = -ext_shift_amounts[total_shift][1]; | |
1309 | if (neg > 0) | |
1310 | neg -= ext_shift_amounts[total_shift][2]; | |
1311 | else | |
1312 | neg = 0; | |
1313 | } | |
1314 | emit_insn (gen_and_shl_scratch (dest, source, | |
1315 | GEN_INT (right), | |
1316 | GEN_INT (mask), | |
1317 | GEN_INT (total_shift + neg), | |
1318 | GEN_INT (neg))); | |
1319 | emit_insn (gen_movsi (dest, dest)); | |
1320 | break; | |
1321 | } | |
1322 | } | |
1323 | return 0; | |
1324 | } | |
1325 | ||
1326 | /* Try to find a good way to implement the combiner pattern | |
1327 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1328 | (sign_extract:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") | |
1329 | (match_operand:SI 2 "const_int_operand" "n") | |
1330 | (match_operand:SI 3 "const_int_operand" "n") | |
1331 | (const_int 0))) | |
1332 | (clobber (reg:SI 18))] | |
1333 | LEFT_RTX is operand 2 in the above pattern, and SIZE_RTX is operand 3. | |
1334 | return 0 for simple left / right shift combination. | |
1335 | return 1 for left shift / 8 bit sign extend / left shift. | |
1336 | return 2 for left shift / 16 bit sign extend / left shift. | |
1337 | return 3 for left shift / 8 bit sign extend / shift / sign extend. | |
1338 | return 4 for left shift / 16 bit sign extend / shift / sign extend. | |
1339 | return 5 for left shift / 16 bit sign extend / right shift | |
1340 | return 6 for < 8 bit sign extend / left shift. | |
1341 | return 7 for < 8 bit sign extend / left shift / single right shift. | |
1342 | If COSTP is nonzero, assign the calculated cost to *COSTP. */ | |
1343 | ||
1344 | int | |
1345 | shl_sext_kind (left_rtx, size_rtx, costp) | |
1346 | rtx left_rtx, size_rtx; | |
1347 | int *costp; | |
1348 | { | |
1349 | int left, size, insize, ext; | |
1350 | int cost, best_cost; | |
1351 | int kind; | |
1352 | ||
1353 | left = INTVAL (left_rtx); | |
1354 | size = INTVAL (size_rtx); | |
1355 | insize = size - left; | |
1356 | if (insize <= 0) | |
1357 | abort (); | |
1358 | /* Default to left / right shift. */ | |
1359 | kind = 0; | |
1360 | best_cost = shift_insns[32 - insize] + ashiftrt_insns[32 - size]; | |
1361 | if (size <= 16) | |
1362 | { | |
1363 | /* 16 bit shift / sign extend / 16 bit shift */ | |
1364 | cost = shift_insns[16 - insize] + 1 + ashiftrt_insns[16 - size]; | |
afad3d2c JW |
1365 | /* If ashiftrt_insns[16 - size] is 8, this choice will be overridden |
1366 | below, by alternative 3 or something even better. */ | |
8d481241 JW |
1367 | if (cost < best_cost) |
1368 | { | |
1369 | kind = 5; | |
1370 | best_cost = cost; | |
1371 | } | |
1372 | } | |
1373 | /* Try a plain sign extend between two shifts. */ | |
1374 | for (ext = 16; ext >= insize; ext -= 8) | |
1375 | { | |
1376 | if (ext <= size) | |
1377 | { | |
1378 | cost = ext_shift_insns[ext - insize] + 1 + shift_insns[size - ext]; | |
1379 | if (cost < best_cost) | |
1380 | { | |
1381 | kind = ext / 8U; | |
1382 | best_cost = cost; | |
1383 | } | |
1384 | } | |
ae9d19c0 JR |
1385 | /* Check if we can do a sloppy shift with a final signed shift |
1386 | restoring the sign. */ | |
1387 | if (EXT_SHIFT_SIGNED (size - ext)) | |
1388 | cost = ext_shift_insns[ext - insize] + ext_shift_insns[size - ext] + 1; | |
1389 | /* If not, maybe it's still cheaper to do the second shift sloppy, | |
1390 | and do a final sign extend? */ | |
1391 | else if (size <= 16) | |
1392 | cost = ext_shift_insns[ext - insize] + 1 | |
1393 | + ext_shift_insns[size > ext ? size - ext : ext - size] + 1; | |
1394 | else | |
1395 | continue; | |
1396 | if (cost < best_cost) | |
8d481241 | 1397 | { |
ae9d19c0 JR |
1398 | kind = ext / 8U + 2; |
1399 | best_cost = cost; | |
8d481241 JW |
1400 | } |
1401 | } | |
1402 | /* Check if we can sign extend in r0 */ | |
1403 | if (insize < 8) | |
1404 | { | |
1405 | cost = 3 + shift_insns[left]; | |
1406 | if (cost < best_cost) | |
1407 | { | |
1408 | kind = 6; | |
1409 | best_cost = cost; | |
1410 | } | |
1411 | /* Try the same with a final signed shift. */ | |
1412 | if (left < 31) | |
1413 | { | |
1414 | cost = 3 + ext_shift_insns[left + 1] + 1; | |
1415 | if (cost < best_cost) | |
1416 | { | |
1417 | kind = 7; | |
1418 | best_cost = cost; | |
1419 | } | |
1420 | } | |
1421 | } | |
1422 | if (TARGET_SH3) | |
1423 | { | |
1424 | /* Try to use a dynamic shift. */ | |
1425 | cost = shift_insns[32 - insize] + 3; | |
1426 | if (cost < best_cost) | |
1427 | { | |
1428 | kind = 0; | |
1429 | best_cost = cost; | |
1430 | } | |
1431 | } | |
1432 | if (costp) | |
1433 | *costp = cost; | |
1434 | return kind; | |
1435 | } | |
1436 | ||
1437 | /* Function to be used in the length attribute of the instructions | |
1438 | implementing this pattern. */ | |
1439 | ||
1440 | int | |
1441 | shl_sext_length (insn) | |
1442 | rtx insn; | |
1443 | { | |
1444 | rtx set_src, left_rtx, size_rtx; | |
1445 | int cost; | |
1446 | ||
1447 | set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); | |
1448 | left_rtx = XEXP (XEXP (set_src, 0), 1); | |
1449 | size_rtx = XEXP (set_src, 1); | |
1450 | shl_sext_kind (left_rtx, size_rtx, &cost); | |
1451 | return cost; | |
1452 | } | |
1453 | ||
1454 | /* Generate rtl for this pattern */ | |
1455 | ||
1456 | int | |
1457 | gen_shl_sext (dest, left_rtx, size_rtx, source) | |
1458 | rtx dest, left_rtx, size_rtx, source; | |
1459 | { | |
1460 | int kind; | |
d00d338c | 1461 | int left, size, insize, cost; |
8d481241 JW |
1462 | rtx operands[3]; |
1463 | ||
d00d338c | 1464 | kind = shl_sext_kind (left_rtx, size_rtx, &cost); |
8d481241 JW |
1465 | left = INTVAL (left_rtx); |
1466 | size = INTVAL (size_rtx); | |
1467 | insize = size - left; | |
1468 | switch (kind) | |
1469 | { | |
1470 | case 1: | |
1471 | case 2: | |
1472 | case 3: | |
1473 | case 4: | |
1474 | { | |
1475 | int ext = kind & 1 ? 8 : 16; | |
1476 | int shift2 = size - ext; | |
1477 | ||
1478 | /* Don't expand fine-grained when combining, because that will | |
1479 | make the pattern fail. */ | |
1480 | if (! rtx_equal_function_value_matters | |
1481 | && ! reload_in_progress && ! reload_completed) | |
1482 | { | |
1483 | emit_insn (gen_shl_sext_ext (dest, source, left_rtx, size_rtx)); | |
1484 | emit_insn (gen_movsi (dest, source)); | |
1485 | break; | |
1486 | } | |
1487 | if (dest != source) | |
1488 | emit_insn (gen_movsi (dest, source)); | |
1489 | operands[0] = dest; | |
afad3d2c JW |
1490 | if (ext - insize) |
1491 | { | |
1492 | operands[2] = GEN_INT (ext - insize); | |
1493 | gen_shifty_hi_op (ASHIFT, operands); | |
1494 | } | |
8d481241 | 1495 | emit_insn (kind & 1 |
afad3d2c JW |
1496 | ? gen_extendqisi2(dest, gen_lowpart (QImode, dest)) |
1497 | : gen_extendhisi2(dest, gen_lowpart (HImode, dest))); | |
8d481241 JW |
1498 | if (kind <= 2) |
1499 | { | |
afad3d2c JW |
1500 | if (shift2) |
1501 | { | |
1502 | operands[2] = GEN_INT (shift2); | |
1503 | gen_shifty_op (ASHIFT, operands); | |
1504 | } | |
8d481241 JW |
1505 | } |
1506 | else | |
1507 | { | |
afad3d2c | 1508 | if (shift2 > 0) |
8d481241 | 1509 | { |
ae9d19c0 JR |
1510 | if (EXT_SHIFT_SIGNED (shift2)) |
1511 | { | |
1512 | operands[2] = GEN_INT (shift2 + 1); | |
1513 | gen_shifty_op (ASHIFT, operands); | |
1514 | operands[2] = GEN_INT (1); | |
1515 | gen_shifty_op (ASHIFTRT, operands); | |
1516 | break; | |
1517 | } | |
8d481241 JW |
1518 | operands[2] = GEN_INT (shift2); |
1519 | gen_shifty_hi_op (ASHIFT, operands); | |
1520 | } | |
afad3d2c | 1521 | else if (shift2) |
8d481241 JW |
1522 | { |
1523 | operands[2] = GEN_INT (-shift2); | |
1524 | gen_shifty_hi_op (LSHIFTRT, operands); | |
1525 | } | |
1526 | emit_insn (size <= 8 | |
afad3d2c JW |
1527 | ? gen_extendqisi2 (dest, gen_lowpart (QImode, dest)) |
1528 | : gen_extendhisi2 (dest, gen_lowpart (HImode, dest))); | |
8d481241 JW |
1529 | } |
1530 | break; | |
1531 | } | |
1532 | case 5: | |
afad3d2c JW |
1533 | { |
1534 | int i = 16 - size; | |
1535 | emit_insn (gen_shl_sext_ext (dest, source, GEN_INT (16 - insize), | |
1536 | GEN_INT (16))); | |
1537 | /* Don't use gen_ashrsi3 because it generates new pseudos. */ | |
1538 | while (--i >= 0) | |
1539 | gen_ashift (ASHIFTRT, 1, dest); | |
1540 | break; | |
1541 | } | |
8d481241 JW |
1542 | case 6: |
1543 | case 7: | |
1544 | /* Don't expand fine-grained when combining, because that will | |
1545 | make the pattern fail. */ | |
1546 | if (! rtx_equal_function_value_matters | |
1547 | && ! reload_in_progress && ! reload_completed) | |
1548 | { | |
1549 | emit_insn (gen_shl_sext_ext (dest, source, left_rtx, size_rtx)); | |
1550 | emit_insn (gen_movsi (dest, source)); | |
1551 | break; | |
1552 | } | |
1553 | emit_insn (gen_andsi3 (dest, source, GEN_INT ((1 << insize) - 1))); | |
1554 | emit_insn (gen_xorsi3 (dest, dest, GEN_INT (1 << (insize - 1)))); | |
1555 | emit_insn (gen_addsi3 (dest, dest, GEN_INT (-1 << (insize - 1)))); | |
1556 | operands[0] = dest; | |
1557 | operands[2] = kind == 7 ? GEN_INT (left + 1) : left_rtx; | |
1558 | gen_shifty_op (ASHIFT, operands); | |
1559 | if (kind == 7) | |
1560 | emit_insn (gen_ashrsi3_k (dest, dest, GEN_INT (1))); | |
1561 | break; | |
1562 | default: | |
1563 | return -1; | |
1564 | } | |
1565 | return 0; | |
1566 | } | |
8aa2a305 JW |
1567 | \f |
1568 | /* The SH cannot load a large constant into a register, constants have to | |
1569 | come from a pc relative load. The reference of a pc relative load | |
1570 | instruction must be less than 1k infront of the instruction. This | |
1571 | means that we often have to dump a constant inside a function, and | |
1572 | generate code to branch around it. | |
bc45ade3 | 1573 | |
8aa2a305 JW |
1574 | It is important to minimize this, since the branches will slow things |
1575 | down and make things bigger. | |
1576 | ||
1577 | Worst case code looks like: | |
1578 | ||
1579 | mov.l L1,rn | |
1580 | bra L2 | |
1581 | nop | |
1582 | align | |
1583 | L1: .long value | |
1584 | L2: | |
1585 | .. | |
1586 | ||
1587 | mov.l L3,rn | |
1588 | bra L4 | |
1589 | nop | |
1590 | align | |
1591 | L3: .long value | |
1592 | L4: | |
1593 | .. | |
1594 | ||
1595 | We fix this by performing a scan before scheduling, which notices which | |
1596 | instructions need to have their operands fetched from the constant table | |
1597 | and builds the table. | |
1598 | ||
1599 | The algorithm is: | |
1600 | ||
1601 | scan, find an instruction which needs a pcrel move. Look forward, find the | |
1602 | last barrier which is within MAX_COUNT bytes of the requirement. | |
1603 | If there isn't one, make one. Process all the instructions between | |
1604 | the find and the barrier. | |
1605 | ||
1606 | In the above example, we can tell that L3 is within 1k of L1, so | |
1607 | the first move can be shrunk from the 3 insn+constant sequence into | |
1608 | just 1 insn, and the constant moved to L3 to make: | |
1609 | ||
1610 | mov.l L1,rn | |
1611 | .. | |
1612 | mov.l L3,rn | |
1613 | bra L4 | |
1614 | nop | |
1615 | align | |
1616 | L3:.long value | |
1617 | L4:.long value | |
1618 | ||
1619 | Then the second move becomes the target for the shortening process. */ | |
1620 | ||
1621 | typedef struct | |
1622 | { | |
1623 | rtx value; /* Value in table. */ | |
1624 | rtx label; /* Label of value. */ | |
1625 | enum machine_mode mode; /* Mode of value. */ | |
1626 | } pool_node; | |
1627 | ||
1628 | /* The maximum number of constants that can fit into one pool, since | |
1629 | the pc relative range is 0...1020 bytes and constants are at least 4 | |
1630 | bytes long. */ | |
1631 | ||
1632 | #define MAX_POOL_SIZE (1020/4) | |
1633 | static pool_node pool_vector[MAX_POOL_SIZE]; | |
1634 | static int pool_size; | |
1635 | ||
1636 | /* ??? If we need a constant in HImode which is the truncated value of a | |
1637 | constant we need in SImode, we could combine the two entries thus saving | |
1638 | two bytes. Is this common enough to be worth the effort of implementing | |
1639 | it? */ | |
1640 | ||
1641 | /* ??? This stuff should be done at the same time that we shorten branches. | |
1642 | As it is now, we must assume that all branches are the maximum size, and | |
1643 | this causes us to almost always output constant pools sooner than | |
1644 | necessary. */ | |
1645 | ||
1646 | /* Add a constant to the pool and return its label. */ | |
1647 | ||
1648 | static rtx | |
1649 | add_constant (x, mode) | |
1650 | rtx x; | |
1651 | enum machine_mode mode; | |
0d7e008e SC |
1652 | { |
1653 | int i; | |
8aa2a305 JW |
1654 | rtx lab; |
1655 | ||
1656 | /* First see if we've already got it. */ | |
1657 | for (i = 0; i < pool_size; i++) | |
0d7e008e | 1658 | { |
8aa2a305 JW |
1659 | if (x->code == pool_vector[i].value->code |
1660 | && mode == pool_vector[i].mode) | |
0d7e008e | 1661 | { |
8aa2a305 JW |
1662 | if (x->code == CODE_LABEL) |
1663 | { | |
1664 | if (XINT (x, 3) != XINT (pool_vector[i].value, 3)) | |
1665 | continue; | |
1666 | } | |
1667 | if (rtx_equal_p (x, pool_vector[i].value)) | |
1668 | return pool_vector[i].label; | |
0d7e008e | 1669 | } |
0d7e008e | 1670 | } |
b9654711 | 1671 | |
8aa2a305 JW |
1672 | /* Need a new one. */ |
1673 | pool_vector[pool_size].value = x; | |
1674 | lab = gen_label_rtx (); | |
1675 | pool_vector[pool_size].mode = mode; | |
1676 | pool_vector[pool_size].label = lab; | |
1677 | pool_size++; | |
1678 | return lab; | |
0d7e008e | 1679 | } |
16bea517 JW |
1680 | |
1681 | /* Output the literal table. */ | |
b9654711 | 1682 | |
b9654711 | 1683 | static void |
0d7e008e SC |
1684 | dump_table (scan) |
1685 | rtx scan; | |
b9654711 | 1686 | { |
0d7e008e | 1687 | int i; |
0d7e008e | 1688 | int need_align = 1; |
b9654711 | 1689 | |
16bea517 | 1690 | /* Do two passes, first time dump out the HI sized constants. */ |
b9654711 | 1691 | |
0d7e008e | 1692 | for (i = 0; i < pool_size; i++) |
b9654711 | 1693 | { |
8aa2a305 JW |
1694 | pool_node *p = &pool_vector[i]; |
1695 | ||
0d7e008e SC |
1696 | if (p->mode == HImode) |
1697 | { | |
1698 | if (need_align) | |
1699 | { | |
1700 | scan = emit_insn_after (gen_align_2 (), scan); | |
1701 | need_align = 0; | |
1702 | } | |
1703 | scan = emit_label_after (p->label, scan); | |
1704 | scan = emit_insn_after (gen_consttable_2 (p->value), scan); | |
1705 | } | |
b9654711 | 1706 | } |
8aa2a305 | 1707 | |
0d7e008e | 1708 | need_align = 1; |
b9654711 | 1709 | |
0d7e008e | 1710 | for (i = 0; i < pool_size; i++) |
b9654711 | 1711 | { |
8aa2a305 | 1712 | pool_node *p = &pool_vector[i]; |
b9654711 | 1713 | |
0d7e008e | 1714 | switch (p->mode) |
b9654711 | 1715 | { |
0d7e008e SC |
1716 | case HImode: |
1717 | break; | |
1718 | case SImode: | |
e577c183 | 1719 | case SFmode: |
0d7e008e | 1720 | if (need_align) |
b9654711 | 1721 | { |
0d7e008e | 1722 | need_align = 0; |
d3ae8277 | 1723 | scan = emit_label_after (gen_label_rtx (), scan); |
0d7e008e | 1724 | scan = emit_insn_after (gen_align_4 (), scan); |
b9654711 | 1725 | } |
0d7e008e SC |
1726 | scan = emit_label_after (p->label, scan); |
1727 | scan = emit_insn_after (gen_consttable_4 (p->value), scan); | |
1728 | break; | |
e577c183 | 1729 | case DFmode: |
0d7e008e SC |
1730 | case DImode: |
1731 | if (need_align) | |
1732 | { | |
1733 | need_align = 0; | |
d3ae8277 | 1734 | scan = emit_label_after (gen_label_rtx (), scan); |
0d7e008e SC |
1735 | scan = emit_insn_after (gen_align_4 (), scan); |
1736 | } | |
1737 | scan = emit_label_after (p->label, scan); | |
1738 | scan = emit_insn_after (gen_consttable_8 (p->value), scan); | |
1739 | break; | |
1740 | default: | |
1741 | abort (); | |
1742 | break; | |
b9654711 SC |
1743 | } |
1744 | } | |
b9654711 | 1745 | |
0d7e008e SC |
1746 | scan = emit_insn_after (gen_consttable_end (), scan); |
1747 | scan = emit_barrier_after (scan); | |
1748 | pool_size = 0; | |
1749 | } | |
b9654711 | 1750 | |
8aa2a305 JW |
1751 | /* Return non-zero if constant would be an ok source for a |
1752 | mov.w instead of a mov.l. */ | |
b9654711 | 1753 | |
16bea517 | 1754 | static int |
8aa2a305 | 1755 | hi_const (src) |
0d7e008e | 1756 | rtx src; |
0d7e008e | 1757 | { |
8aa2a305 JW |
1758 | return (GET_CODE (src) == CONST_INT |
1759 | && INTVAL (src) >= -32768 | |
1760 | && INTVAL (src) <= 32767); | |
b9654711 SC |
1761 | } |
1762 | ||
8aa2a305 JW |
1763 | /* Non-zero if the insn is a move instruction which needs to be fixed. */ |
1764 | ||
1765 | /* ??? For a DImode/DFmode moves, we don't need to fix it if each half of the | |
1766 | CONST_DOUBLE input value is CONST_OK_FOR_I. For a SFmode move, we don't | |
1767 | need to fix it if the input value is CONST_OK_FOR_I. */ | |
1768 | ||
1769 | static int | |
1770 | broken_move (insn) | |
1771 | rtx insn; | |
b9654711 | 1772 | { |
e577c183 JR |
1773 | if (GET_CODE (insn) == INSN) |
1774 | { | |
1775 | rtx pat = PATTERN (insn); | |
1776 | if (GET_CODE (pat) == PARALLEL) | |
1777 | pat = XVECEXP (pat, 0, 0); | |
1778 | if (GET_CODE (pat) == SET | |
1779 | /* We can load any 8 bit value if we don't care what the high | |
1780 | order bits end up as. */ | |
1781 | && GET_MODE (SET_DEST (pat)) != QImode | |
1782 | && CONSTANT_P (SET_SRC (pat)) | |
1783 | && ! (GET_CODE (SET_SRC (pat)) == CONST_DOUBLE | |
1784 | && (fp_zero_operand (SET_SRC (pat)) | |
1785 | || fp_one_operand (SET_SRC (pat))) | |
1786 | && GET_CODE (SET_DEST (pat)) == REG | |
1787 | && REGNO (SET_DEST (pat)) >= FIRST_FP_REG | |
1788 | && REGNO (SET_DEST (pat)) <= LAST_FP_REG) | |
1789 | && (GET_CODE (SET_SRC (pat)) != CONST_INT | |
1790 | || ! CONST_OK_FOR_I (INTVAL (SET_SRC (pat))))) | |
1791 | return 1; | |
1792 | } | |
d3ae8277 | 1793 | |
8aa2a305 | 1794 | return 0; |
b9654711 | 1795 | } |
b9654711 | 1796 | |
8aa2a305 JW |
1797 | /* Find the last barrier from insn FROM which is close enough to hold the |
1798 | constant pool. If we can't find one, then create one near the end of | |
1799 | the range. */ | |
b9654711 | 1800 | |
5325c0fa JW |
1801 | /* ??? It would be good to put constant pool tables between a case jump and |
1802 | the jump table. This fails for two reasons. First, there is no | |
1803 | barrier after the case jump. This is a bug in the casesi pattern. | |
1804 | Second, inserting the table here may break the mova instruction that | |
1805 | loads the jump table address, by moving the jump table too far away. | |
1806 | We fix that problem by never outputting the constant pool between a mova | |
1807 | and its label. */ | |
1808 | ||
8aa2a305 | 1809 | static rtx |
06c386ea SC |
1810 | find_barrier (from) |
1811 | rtx from; | |
b9654711 | 1812 | { |
0d7e008e SC |
1813 | int count_si = 0; |
1814 | int count_hi = 0; | |
1815 | int found_hi = 0; | |
1816 | int found_si = 0; | |
1817 | rtx found_barrier = 0; | |
5325c0fa | 1818 | rtx found_mova = 0; |
c17f53a8 JW |
1819 | int si_limit; |
1820 | int hi_limit; | |
8aa2a305 JW |
1821 | |
1822 | /* For HImode: range is 510, add 4 because pc counts from address of | |
1823 | second instruction after this one, subtract 2 for the jump instruction | |
3adbde60 JW |
1824 | that we may need to emit before the table, subtract 2 for the instruction |
1825 | that fills the jump delay slot (in very rare cases, reorg will take an | |
1826 | instruction from after the constant pool or will leave the delay slot | |
1827 | empty). This gives 510. | |
8aa2a305 JW |
1828 | For SImode: range is 1020, add 4 because pc counts from address of |
1829 | second instruction after this one, subtract 2 in case pc is 2 byte | |
1830 | aligned, subtract 2 for the jump instruction that we may need to emit | |
3adbde60 JW |
1831 | before the table, subtract 2 for the instruction that fills the jump |
1832 | delay slot. This gives 1018. */ | |
c17f53a8 JW |
1833 | |
1834 | /* If not optimizing, then it is possible that the jump instruction we add | |
1835 | won't be shortened, and thus will have a length of 14 instead of 2. | |
1836 | We must adjust the limits downwards to account for this, giving a limit | |
1837 | of 1008 for SImode and 500 for HImode. */ | |
1838 | ||
1839 | if (optimize) | |
1840 | { | |
3adbde60 JW |
1841 | si_limit = 1018; |
1842 | hi_limit = 510; | |
c17f53a8 JW |
1843 | } |
1844 | else | |
1845 | { | |
1846 | si_limit = 1008; | |
1847 | hi_limit = 500; | |
1848 | } | |
1849 | ||
e4fa6b06 ILT |
1850 | /* If not optimizing for space, then the constant pool will be |
1851 | aligned to a 4 to 16 byte boundary. We must make room for that | |
1852 | alignment that by reducing the limits. | |
1853 | ??? It would be better to not align the constant pool, but | |
1854 | ASM_OUTPUT_ALIGN_CODE does not make any provision for basing the | |
1855 | alignment on the instruction. */ | |
1856 | ||
1857 | if (! TARGET_SMALLCODE) | |
1858 | { | |
1859 | if (TARGET_SH3 || TARGET_SH3E) | |
1860 | { | |
1861 | si_limit -= 14; | |
1862 | hi_limit -= 14; | |
1863 | } | |
1864 | else | |
1865 | { | |
1866 | si_limit -= 2; | |
1867 | hi_limit -= 2; | |
1868 | } | |
1869 | } | |
1870 | ||
c17f53a8 | 1871 | while (from && count_si < si_limit && count_hi < hi_limit) |
0d7e008e | 1872 | { |
5dbcc9c0 | 1873 | int inc = get_attr_length (from); |
8aa2a305 | 1874 | |
0d7e008e | 1875 | if (GET_CODE (from) == BARRIER) |
8aa2a305 JW |
1876 | found_barrier = from; |
1877 | ||
8aa2a305 | 1878 | if (broken_move (from)) |
0d7e008e | 1879 | { |
c17f53a8 JW |
1880 | rtx pat = PATTERN (from); |
1881 | rtx src = SET_SRC (pat); | |
1882 | rtx dst = SET_DEST (pat); | |
1883 | enum machine_mode mode = GET_MODE (dst); | |
1884 | ||
1885 | /* We must explicitly check the mode, because sometimes the | |
1886 | front end will generate code to load unsigned constants into | |
1887 | HImode targets without properly sign extending them. */ | |
1888 | if (mode == HImode || (mode == SImode && hi_const (src))) | |
00e94d65 RK |
1889 | { |
1890 | found_hi = 1; | |
1891 | /* We put the short constants before the long constants, so | |
1892 | we must count the length of short constants in the range | |
1893 | for the long constants. */ | |
1894 | /* ??? This isn't optimal, but is easy to do. */ | |
1895 | if (found_si) | |
1896 | count_si += 2; | |
1897 | } | |
0d7e008e SC |
1898 | else |
1899 | found_si = 1; | |
0d7e008e | 1900 | } |
5325c0fa | 1901 | |
5325c0fa JW |
1902 | if (GET_CODE (from) == INSN |
1903 | && GET_CODE (PATTERN (from)) == SET | |
16bea517 JW |
1904 | && GET_CODE (SET_SRC (PATTERN (from))) == UNSPEC |
1905 | && XINT (SET_SRC (PATTERN (from)), 1) == 1) | |
5325c0fa JW |
1906 | found_mova = from; |
1907 | else if (GET_CODE (from) == JUMP_INSN | |
1908 | && (GET_CODE (PATTERN (from)) == ADDR_VEC | |
1909 | || GET_CODE (PATTERN (from)) == ADDR_DIFF_VEC)) | |
1910 | found_mova = 0; | |
1911 | ||
0d7e008e SC |
1912 | if (found_si) |
1913 | count_si += inc; | |
1914 | if (found_hi) | |
1915 | count_hi += inc; | |
1916 | from = NEXT_INSN (from); | |
1917 | } | |
1918 | ||
5325c0fa JW |
1919 | /* Insert the constant pool table before the mova instruction, to prevent |
1920 | the mova label reference from going out of range. */ | |
1921 | if (found_mova) | |
1922 | from = found_mova; | |
1923 | ||
8aa2a305 | 1924 | if (! found_barrier) |
b9654711 | 1925 | { |
8aa2a305 JW |
1926 | /* We didn't find a barrier in time to dump our stuff, |
1927 | so we'll make one. */ | |
0d7e008e | 1928 | rtx label = gen_label_rtx (); |
8aa2a305 | 1929 | |
5dbcc9c0 RK |
1930 | /* If we exceeded the range, then we must back up over the last |
1931 | instruction we looked at. Otherwise, we just need to undo the | |
1932 | NEXT_INSN at the end of the loop. */ | |
c17f53a8 | 1933 | if (count_hi > hi_limit || count_si > si_limit) |
5dbcc9c0 RK |
1934 | from = PREV_INSN (PREV_INSN (from)); |
1935 | else | |
1936 | from = PREV_INSN (from); | |
1937 | ||
8aa2a305 JW |
1938 | /* Walk back to be just before any jump or label. |
1939 | Putting it before a label reduces the number of times the branch | |
1940 | around the constant pool table will be hit. Putting it before | |
1941 | a jump makes it more likely that the bra delay slot will be | |
1942 | filled. */ | |
1943 | while (GET_CODE (from) == JUMP_INSN || GET_CODE (from) == NOTE | |
8e87e161 | 1944 | || GET_CODE (from) == CODE_LABEL) |
8aa2a305 JW |
1945 | from = PREV_INSN (from); |
1946 | ||
0d7e008e SC |
1947 | from = emit_jump_insn_after (gen_jump (label), from); |
1948 | JUMP_LABEL (from) = label; | |
e081ed26 | 1949 | LABEL_NUSES (label) = 1; |
0d7e008e SC |
1950 | found_barrier = emit_barrier_after (from); |
1951 | emit_label_after (label, found_barrier); | |
b9654711 | 1952 | } |
b9654711 | 1953 | |
8aa2a305 | 1954 | return found_barrier; |
0d7e008e | 1955 | } |
b9654711 | 1956 | |
4787bce0 JW |
1957 | /* If the instruction INSN is implemented by a special function, and we can |
1958 | positively find the register that is used to call the sfunc, and this | |
1959 | register is not used anywhere else in this instruction - except as the | |
1960 | destination of a set, return this register; else, return 0. */ | |
1961 | static rtx | |
1962 | sfunc_uses_reg (insn) | |
1963 | rtx insn; | |
1964 | { | |
1965 | int i; | |
1966 | rtx pattern, part, reg_part, reg; | |
1967 | ||
1968 | if (GET_CODE (insn) != INSN) | |
1969 | return 0; | |
1970 | pattern = PATTERN (insn); | |
1971 | if (GET_CODE (pattern) != PARALLEL || get_attr_type (insn) != TYPE_SFUNC) | |
1972 | return 0; | |
1973 | ||
1974 | for (reg_part = 0, i = XVECLEN (pattern, 0) - 1; i >= 1; i--) | |
1975 | { | |
1976 | part = XVECEXP (pattern, 0, i); | |
1977 | if (GET_CODE (part) == USE) | |
1978 | reg_part = part; | |
1979 | } | |
1980 | if (! reg_part) | |
1981 | return 0; | |
1982 | reg = XEXP (reg_part, 0); | |
1983 | for (i = XVECLEN (pattern, 0) - 1; i >= 0; i--) | |
1984 | { | |
1985 | part = XVECEXP (pattern, 0, i); | |
1986 | if (part == reg_part) | |
1987 | continue; | |
1988 | if (reg_mentioned_p (reg, ((GET_CODE (part) == SET | |
1989 | && GET_CODE (SET_DEST (part)) == REG) | |
1990 | ? SET_SRC (part) : part))) | |
1991 | return 0; | |
1992 | } | |
1993 | return reg; | |
1994 | } | |
1995 | ||
933c3ba3 JW |
1996 | /* See if the only way in which INSN uses REG is by calling it, or by |
1997 | setting it while calling it. Set *SET to a SET rtx if the register | |
1998 | is set by INSN. */ | |
1999 | ||
2000 | static int | |
2001 | noncall_uses_reg (reg, insn, set) | |
2002 | rtx reg; | |
2003 | rtx insn; | |
2004 | rtx *set; | |
2005 | { | |
4787bce0 | 2006 | rtx pattern, reg2; |
933c3ba3 JW |
2007 | |
2008 | *set = NULL_RTX; | |
2009 | ||
4787bce0 JW |
2010 | reg2 = sfunc_uses_reg (insn); |
2011 | if (reg2 && REGNO (reg2) == REGNO (reg)) | |
2012 | { | |
2013 | pattern = single_set (insn); | |
2014 | if (pattern | |
2015 | && GET_CODE (SET_DEST (pattern)) == REG | |
2016 | && REGNO (reg) == REGNO (SET_DEST (pattern))) | |
2017 | *set = pattern; | |
2018 | return 0; | |
2019 | } | |
933c3ba3 JW |
2020 | if (GET_CODE (insn) != CALL_INSN) |
2021 | { | |
2022 | /* We don't use rtx_equal_p because we don't care if the mode is | |
2023 | different. */ | |
2024 | pattern = single_set (insn); | |
2025 | if (pattern | |
2026 | && GET_CODE (SET_DEST (pattern)) == REG | |
2027 | && REGNO (reg) == REGNO (SET_DEST (pattern))) | |
2028 | { | |
4787bce0 JW |
2029 | rtx par, part; |
2030 | int i; | |
2031 | ||
933c3ba3 | 2032 | *set = pattern; |
4787bce0 JW |
2033 | par = PATTERN (insn); |
2034 | if (GET_CODE (par) == PARALLEL) | |
2035 | for (i = XVECLEN (par, 0) - 1; i >= 0; i--) | |
2036 | { | |
2037 | part = XVECEXP (par, 0, i); | |
2038 | if (GET_CODE (part) != SET && reg_mentioned_p (reg, part)) | |
2039 | return 1; | |
2040 | } | |
2041 | return reg_mentioned_p (reg, SET_SRC (pattern)); | |
933c3ba3 JW |
2042 | } |
2043 | ||
2044 | return 1; | |
2045 | } | |
2046 | ||
2047 | pattern = PATTERN (insn); | |
2048 | ||
2049 | if (GET_CODE (pattern) == PARALLEL) | |
2050 | { | |
2051 | int i; | |
2052 | ||
2053 | for (i = XVECLEN (pattern, 0) - 1; i >= 1; i--) | |
2054 | if (reg_mentioned_p (reg, XVECEXP (pattern, 0, i))) | |
2055 | return 1; | |
2056 | pattern = XVECEXP (pattern, 0, 0); | |
2057 | } | |
2058 | ||
2059 | if (GET_CODE (pattern) == SET) | |
2060 | { | |
2061 | if (reg_mentioned_p (reg, SET_DEST (pattern))) | |
2062 | { | |
2063 | /* We don't use rtx_equal_p, because we don't care if the | |
2064 | mode is different. */ | |
2065 | if (GET_CODE (SET_DEST (pattern)) != REG | |
2066 | || REGNO (reg) != REGNO (SET_DEST (pattern))) | |
2067 | return 1; | |
2068 | ||
2069 | *set = pattern; | |
2070 | } | |
2071 | ||
2072 | pattern = SET_SRC (pattern); | |
2073 | } | |
2074 | ||
2075 | if (GET_CODE (pattern) != CALL | |
2076 | || GET_CODE (XEXP (pattern, 0)) != MEM | |
2077 | || ! rtx_equal_p (reg, XEXP (XEXP (pattern, 0), 0))) | |
2078 | return 1; | |
2079 | ||
2080 | return 0; | |
2081 | } | |
2082 | ||
8aa2a305 | 2083 | /* Exported to toplev.c. |
b9654711 | 2084 | |
933c3ba3 JW |
2085 | Do a final pass over the function, just before delayed branch |
2086 | scheduling. */ | |
b9654711 | 2087 | |
0d7e008e SC |
2088 | void |
2089 | machine_dependent_reorg (first) | |
2090 | rtx first; | |
2091 | { | |
2092 | rtx insn; | |
8aa2a305 | 2093 | |
933c3ba3 JW |
2094 | /* If relaxing, generate pseudo-ops to associate function calls with |
2095 | the symbols they call. It does no harm to not generate these | |
2096 | pseudo-ops. However, when we can generate them, it enables to | |
2097 | linker to potentially relax the jsr to a bsr, and eliminate the | |
2098 | register load and, possibly, the constant pool entry. */ | |
2099 | ||
2100 | if (TARGET_RELAX) | |
2101 | { | |
2102 | /* Remove all REG_LABEL notes. We want to use them for our own | |
2103 | purposes. This works because none of the remaining passes | |
2104 | need to look at them. | |
2105 | ||
2106 | ??? But it may break in the future. We should use a machine | |
2107 | dependent REG_NOTE, or some other approach entirely. */ | |
2108 | for (insn = first; insn; insn = NEXT_INSN (insn)) | |
2109 | { | |
2110 | if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') | |
2111 | { | |
2112 | rtx note; | |
2113 | ||
2114 | while ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != 0) | |
2115 | remove_note (insn, note); | |
2116 | } | |
2117 | } | |
2118 | ||
2119 | for (insn = first; insn; insn = NEXT_INSN (insn)) | |
2120 | { | |
2121 | rtx pattern, reg, link, set, scan, dies, label; | |
2122 | int rescan = 0, foundinsn = 0; | |
2123 | ||
4787bce0 JW |
2124 | if (GET_CODE (insn) == CALL_INSN) |
2125 | { | |
2126 | pattern = PATTERN (insn); | |
933c3ba3 | 2127 | |
4787bce0 JW |
2128 | if (GET_CODE (pattern) == PARALLEL) |
2129 | pattern = XVECEXP (pattern, 0, 0); | |
2130 | if (GET_CODE (pattern) == SET) | |
2131 | pattern = SET_SRC (pattern); | |
933c3ba3 | 2132 | |
4787bce0 JW |
2133 | if (GET_CODE (pattern) != CALL |
2134 | || GET_CODE (XEXP (pattern, 0)) != MEM) | |
2135 | continue; | |
933c3ba3 | 2136 | |
4787bce0 JW |
2137 | reg = XEXP (XEXP (pattern, 0), 0); |
2138 | } | |
2139 | else | |
2140 | { | |
2141 | reg = sfunc_uses_reg (insn); | |
2142 | if (! reg) | |
2143 | continue; | |
2144 | } | |
933c3ba3 | 2145 | |
933c3ba3 JW |
2146 | if (GET_CODE (reg) != REG) |
2147 | continue; | |
2148 | ||
2149 | /* This is a function call via REG. If the only uses of REG | |
2150 | between the time that it is set and the time that it dies | |
2151 | are in function calls, then we can associate all the | |
2152 | function calls with the setting of REG. */ | |
2153 | ||
2154 | for (link = LOG_LINKS (insn); link; link = XEXP (link, 1)) | |
2155 | { | |
1075deda ILT |
2156 | if (REG_NOTE_KIND (link) != 0) |
2157 | continue; | |
933c3ba3 JW |
2158 | set = single_set (XEXP (link, 0)); |
2159 | if (set && rtx_equal_p (reg, SET_DEST (set))) | |
2160 | { | |
2161 | link = XEXP (link, 0); | |
2162 | break; | |
2163 | } | |
2164 | } | |
2165 | ||
2166 | if (! link) | |
2167 | { | |
2168 | /* ??? Sometimes global register allocation will have | |
2169 | deleted the insn pointed to by LOG_LINKS. Try | |
2170 | scanning backward to find where the register is set. */ | |
2171 | for (scan = PREV_INSN (insn); | |
2172 | scan && GET_CODE (scan) != CODE_LABEL; | |
2173 | scan = PREV_INSN (scan)) | |
2174 | { | |
2175 | if (GET_RTX_CLASS (GET_CODE (scan)) != 'i') | |
2176 | continue; | |
2177 | ||
2178 | if (! reg_mentioned_p (reg, scan)) | |
2179 | continue; | |
2180 | ||
2181 | if (noncall_uses_reg (reg, scan, &set)) | |
2182 | break; | |
2183 | ||
2184 | if (set) | |
2185 | { | |
2186 | link = scan; | |
2187 | break; | |
2188 | } | |
2189 | } | |
2190 | } | |
2191 | ||
2192 | if (! link) | |
2193 | continue; | |
2194 | ||
2195 | /* The register is set at LINK. */ | |
2196 | ||
2197 | /* We can only optimize the function call if the register is | |
2198 | being set to a symbol. In theory, we could sometimes | |
2199 | optimize calls to a constant location, but the assembler | |
2200 | and linker do not support that at present. */ | |
2201 | if (GET_CODE (SET_SRC (set)) != SYMBOL_REF | |
2202 | && GET_CODE (SET_SRC (set)) != LABEL_REF) | |
2203 | continue; | |
2204 | ||
2205 | /* Scan forward from LINK to the place where REG dies, and | |
2206 | make sure that the only insns which use REG are | |
2207 | themselves function calls. */ | |
2208 | ||
c1e8e6bd JW |
2209 | /* ??? This doesn't work for call targets that were allocated |
2210 | by reload, since there may not be a REG_DEAD note for the | |
2211 | register. */ | |
2212 | ||
933c3ba3 JW |
2213 | dies = NULL_RTX; |
2214 | for (scan = NEXT_INSN (link); scan; scan = NEXT_INSN (scan)) | |
2215 | { | |
2216 | rtx scanset; | |
2217 | ||
c1e8e6bd JW |
2218 | /* Don't try to trace forward past a CODE_LABEL if we haven't |
2219 | seen INSN yet. Ordinarily, we will only find the setting insn | |
2220 | in LOG_LINKS if it is in the same basic block. However, | |
2221 | cross-jumping can insert code labels in between the load and | |
2222 | the call, and can result in situations where a single call | |
2223 | insn may have two targets depending on where we came from. */ | |
2224 | ||
2225 | if (GET_CODE (scan) == CODE_LABEL && ! foundinsn) | |
2226 | break; | |
2227 | ||
933c3ba3 JW |
2228 | if (GET_RTX_CLASS (GET_CODE (scan)) != 'i') |
2229 | continue; | |
2230 | ||
2231 | /* Don't try to trace forward past a JUMP. To optimize | |
2232 | safely, we would have to check that all the | |
c1e8e6bd | 2233 | instructions at the jump destination did not use REG. */ |
933c3ba3 | 2234 | |
c1e8e6bd | 2235 | if (GET_CODE (scan) == JUMP_INSN) |
933c3ba3 JW |
2236 | break; |
2237 | ||
2238 | if (! reg_mentioned_p (reg, scan)) | |
2239 | continue; | |
2240 | ||
2241 | if (noncall_uses_reg (reg, scan, &scanset)) | |
2242 | break; | |
2243 | ||
2244 | if (scan == insn) | |
2245 | foundinsn = 1; | |
2246 | ||
4787bce0 JW |
2247 | if (scan != insn |
2248 | && (GET_CODE (scan) == CALL_INSN || sfunc_uses_reg (scan))) | |
933c3ba3 JW |
2249 | { |
2250 | /* There is a function call to this register other | |
2251 | than the one we are checking. If we optimize | |
2252 | this call, we need to rescan again below. */ | |
2253 | rescan = 1; | |
2254 | } | |
2255 | ||
2256 | /* ??? We shouldn't have to worry about SCANSET here. | |
2257 | We should just be able to check for a REG_DEAD note | |
2258 | on a function call. However, the REG_DEAD notes are | |
2259 | apparently not dependable around libcalls; c-torture | |
2260 | execute/920501-2 is a test case. If SCANSET is set, | |
2261 | then this insn sets the register, so it must have | |
2262 | died earlier. Unfortunately, this will only handle | |
2263 | the cases in which the register is, in fact, set in a | |
2264 | later insn. */ | |
2265 | ||
2266 | /* ??? We shouldn't have to use FOUNDINSN here. | |
2267 | However, the LOG_LINKS fields are apparently not | |
2268 | entirely reliable around libcalls; | |
2269 | newlib/libm/math/e_pow.c is a test case. Sometimes | |
2270 | an insn will appear in LOG_LINKS even though it is | |
2271 | not the most recent insn which sets the register. */ | |
2272 | ||
2273 | if (foundinsn | |
2274 | && (scanset | |
2275 | || find_reg_note (scan, REG_DEAD, reg))) | |
2276 | { | |
2277 | dies = scan; | |
2278 | break; | |
2279 | } | |
2280 | } | |
2281 | ||
2282 | if (! dies) | |
2283 | { | |
2284 | /* Either there was a branch, or some insn used REG | |
2285 | other than as a function call address. */ | |
2286 | continue; | |
2287 | } | |
2288 | ||
2289 | /* Create a code label, and put it in a REG_LABEL note on | |
2290 | the insn which sets the register, and on each call insn | |
2291 | which uses the register. In final_prescan_insn we look | |
2292 | for the REG_LABEL notes, and output the appropriate label | |
2293 | or pseudo-op. */ | |
2294 | ||
2295 | label = gen_label_rtx (); | |
2296 | REG_NOTES (link) = gen_rtx (EXPR_LIST, REG_LABEL, label, | |
2297 | REG_NOTES (link)); | |
2298 | REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_LABEL, label, | |
2299 | REG_NOTES (insn)); | |
2300 | if (rescan) | |
2301 | { | |
2302 | scan = link; | |
2303 | do | |
2304 | { | |
4787bce0 JW |
2305 | rtx reg2; |
2306 | ||
933c3ba3 JW |
2307 | scan = NEXT_INSN (scan); |
2308 | if (scan != insn | |
4787bce0 JW |
2309 | && ((GET_CODE (scan) == CALL_INSN |
2310 | && reg_mentioned_p (reg, scan)) | |
2311 | || ((reg2 = sfunc_uses_reg (scan)) | |
2312 | && REGNO (reg2) == REGNO (reg)))) | |
933c3ba3 JW |
2313 | REG_NOTES (scan) = gen_rtx (EXPR_LIST, REG_LABEL, |
2314 | label, REG_NOTES (scan)); | |
2315 | } | |
2316 | while (scan != dies); | |
2317 | } | |
2318 | } | |
2319 | } | |
2320 | ||
2321 | /* Scan the function looking for move instructions which have to be | |
2322 | changed to pc-relative loads and insert the literal tables. */ | |
2323 | ||
0d7e008e SC |
2324 | for (insn = first; insn; insn = NEXT_INSN (insn)) |
2325 | { | |
2326 | if (broken_move (insn)) | |
2327 | { | |
0d7e008e | 2328 | rtx scan; |
8aa2a305 JW |
2329 | /* Scan ahead looking for a barrier to stick the constant table |
2330 | behind. */ | |
0d7e008e | 2331 | rtx barrier = find_barrier (insn); |
b9654711 | 2332 | |
16bea517 | 2333 | /* Now find all the moves between the points and modify them. */ |
0d7e008e SC |
2334 | for (scan = insn; scan != barrier; scan = NEXT_INSN (scan)) |
2335 | { | |
2336 | if (broken_move (scan)) | |
2337 | { | |
e577c183 JR |
2338 | rtx *patp = &PATTERN (scan), pat = *patp; |
2339 | rtx src, dst; | |
0d7e008e SC |
2340 | rtx lab; |
2341 | rtx newinsn; | |
2342 | rtx newsrc; | |
e577c183 JR |
2343 | enum machine_mode mode; |
2344 | ||
2345 | if (GET_CODE (pat) == PARALLEL) | |
2346 | patp = &XVECEXP (pat, 0, 0), pat = *patp; | |
2347 | src = SET_SRC (pat); | |
2348 | dst = SET_DEST (pat); | |
2349 | mode = GET_MODE (dst); | |
0d7e008e SC |
2350 | |
2351 | if (mode == SImode && hi_const (src)) | |
2352 | { | |
23ed92ca | 2353 | int offset = 0; |
8aa2a305 | 2354 | |
0d7e008e | 2355 | mode = HImode; |
d3ae8277 | 2356 | while (GET_CODE (dst) == SUBREG) |
23ed92ca JW |
2357 | { |
2358 | offset += SUBREG_WORD (dst); | |
2359 | dst = SUBREG_REG (dst); | |
2360 | } | |
2361 | dst = gen_rtx (REG, HImode, REGNO (dst) + offset); | |
0d7e008e | 2362 | } |
8aa2a305 | 2363 | |
0d7e008e SC |
2364 | lab = add_constant (src, mode); |
2365 | newsrc = gen_rtx (MEM, mode, | |
2366 | gen_rtx (LABEL_REF, VOIDmode, lab)); | |
8aa2a305 | 2367 | RTX_UNCHANGING_P (newsrc) = 1; |
e577c183 JR |
2368 | *patp = gen_rtx (SET, VOIDmode, dst, newsrc); |
2369 | INSN_CODE (scan) = -1; | |
0d7e008e SC |
2370 | } |
2371 | } | |
2372 | dump_table (barrier); | |
2373 | } | |
2374 | } | |
b9654711 SC |
2375 | } |
2376 | ||
8aa2a305 | 2377 | /* Dump out instruction addresses, which is useful for debugging the |
933c3ba3 JW |
2378 | constant pool table stuff. |
2379 | ||
2380 | If relaxing, output the label and pseudo-ops used to link together | |
2381 | calls and the instruction which set the registers. */ | |
8aa2a305 JW |
2382 | |
2383 | /* ??? This is unnecessary, and probably should be deleted. This makes | |
2384 | the insn_addresses declaration above unnecessary. */ | |
2385 | ||
2386 | /* ??? The addresses printed by this routine for insns are nonsense for | |
2387 | insns which are inside of a sequence where none of the inner insns have | |
2388 | variable length. This is because the second pass of shorten_branches | |
2389 | does not bother to update them. */ | |
0d7e008e | 2390 | |
8e87e161 | 2391 | void |
8aa2a305 JW |
2392 | final_prescan_insn (insn, opvec, noperands) |
2393 | rtx insn; | |
2394 | rtx *opvec; | |
2395 | int noperands; | |
b9654711 | 2396 | { |
8aa2a305 JW |
2397 | if (TARGET_DUMPISIZE) |
2398 | fprintf (asm_out_file, "\n! at %04x\n", insn_addresses[INSN_UID (insn)]); | |
933c3ba3 JW |
2399 | |
2400 | if (TARGET_RELAX) | |
2401 | { | |
2402 | rtx note; | |
2403 | ||
2404 | note = find_reg_note (insn, REG_LABEL, NULL_RTX); | |
2405 | if (note) | |
2406 | { | |
2407 | rtx pattern; | |
2408 | ||
2409 | pattern = PATTERN (insn); | |
2410 | if (GET_CODE (pattern) == PARALLEL) | |
2411 | pattern = XVECEXP (pattern, 0, 0); | |
2412 | if (GET_CODE (pattern) == CALL | |
2413 | || (GET_CODE (pattern) == SET | |
4787bce0 JW |
2414 | && (GET_CODE (SET_SRC (pattern)) == CALL |
2415 | || get_attr_type (insn) == TYPE_SFUNC))) | |
933c3ba3 JW |
2416 | fprintf (asm_out_file, "\t.uses L%d\n", |
2417 | CODE_LABEL_NUMBER (XEXP (note, 0))); | |
2418 | else if (GET_CODE (pattern) == SET) | |
2419 | ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", | |
2420 | CODE_LABEL_NUMBER (XEXP (note, 0))); | |
2421 | else | |
2422 | abort (); | |
2423 | } | |
2424 | } | |
0d7e008e | 2425 | } |
b9654711 | 2426 | |
8aa2a305 JW |
2427 | /* Dump out any constants accumulated in the final pass. These will |
2428 | will only be labels. */ | |
b9654711 | 2429 | |
8aa2a305 JW |
2430 | char * |
2431 | output_jump_label_table () | |
0d7e008e | 2432 | { |
8aa2a305 JW |
2433 | int i; |
2434 | ||
2435 | if (pool_size) | |
2436 | { | |
2437 | fprintf (asm_out_file, "\t.align 2\n"); | |
2438 | for (i = 0; i < pool_size; i++) | |
2439 | { | |
2440 | pool_node *p = &pool_vector[i]; | |
2441 | ||
2442 | ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", | |
2443 | CODE_LABEL_NUMBER (p->label)); | |
2444 | output_asm_insn (".long %O0", &p->value); | |
2445 | } | |
2446 | pool_size = 0; | |
2447 | } | |
b9654711 | 2448 | |
8aa2a305 JW |
2449 | return ""; |
2450 | } | |
2451 | \f | |
2452 | /* A full frame looks like: | |
16bea517 JW |
2453 | |
2454 | arg-5 | |
2455 | arg-4 | |
2456 | [ if current_function_anonymous_args | |
2457 | arg-3 | |
2458 | arg-2 | |
2459 | arg-1 | |
2460 | arg-0 ] | |
2461 | saved-fp | |
2462 | saved-r10 | |
2463 | saved-r11 | |
2464 | saved-r12 | |
2465 | saved-pr | |
2466 | local-n | |
2467 | .. | |
2468 | local-1 | |
2469 | local-0 <- fp points here. */ | |
8e87e161 | 2470 | |
8aa2a305 JW |
2471 | /* Number of bytes pushed for anonymous args, used to pass information |
2472 | between expand_prologue and expand_epilogue. */ | |
2473 | ||
2474 | static int extra_push; | |
2475 | ||
2476 | /* Adjust the stack and return the number of bytes taken to do it. */ | |
2477 | ||
2478 | static void | |
46d81ffa | 2479 | output_stack_adjust (size, reg) |
8aa2a305 | 2480 | int size; |
46d81ffa | 2481 | rtx reg; |
8aa2a305 JW |
2482 | { |
2483 | if (size) | |
2484 | { | |
2485 | rtx val = GEN_INT (size); | |
2486 | rtx insn; | |
2487 | ||
2488 | if (! CONST_OK_FOR_I (size)) | |
2489 | { | |
2490 | rtx reg = gen_rtx (REG, SImode, 3); | |
2491 | emit_insn (gen_movsi (reg, val)); | |
2492 | val = reg; | |
2493 | } | |
2494 | ||
46d81ffa | 2495 | insn = gen_addsi3 (reg, reg, val); |
8aa2a305 JW |
2496 | emit_insn (insn); |
2497 | } | |
2498 | } | |
2499 | ||
2500 | /* Output RTL to push register RN onto the stack. */ | |
2501 | ||
2502 | static void | |
2503 | push (rn) | |
2504 | int rn; | |
2505 | { | |
2506 | rtx x; | |
1a95a963 JW |
2507 | if ((rn >= FIRST_FP_REG && rn <= LAST_FP_REG) |
2508 | || rn == FPUL_REG) | |
2509 | x = emit_insn (gen_push_e (gen_rtx (REG, SFmode, rn))); | |
2510 | else | |
2511 | x = emit_insn (gen_push (gen_rtx (REG, SImode, rn))); | |
2512 | ||
8aa2a305 JW |
2513 | REG_NOTES (x) = gen_rtx (EXPR_LIST, REG_INC, |
2514 | gen_rtx(REG, SImode, STACK_POINTER_REGNUM), 0); | |
2515 | } | |
2516 | ||
2517 | /* Output RTL to pop register RN from the stack. */ | |
2518 | ||
2519 | static void | |
2520 | pop (rn) | |
2521 | int rn; | |
2522 | { | |
2523 | rtx x; | |
1a95a963 JW |
2524 | if ((rn >= FIRST_FP_REG && rn <= LAST_FP_REG) |
2525 | || rn == FPUL_REG) | |
2526 | x = emit_insn (gen_pop_e (gen_rtx (REG, SFmode, rn))); | |
2527 | else | |
2528 | x = emit_insn (gen_pop (gen_rtx (REG, SImode, rn))); | |
2529 | ||
8aa2a305 JW |
2530 | REG_NOTES (x) = gen_rtx (EXPR_LIST, REG_INC, |
2531 | gen_rtx(REG, SImode, STACK_POINTER_REGNUM), 0); | |
2532 | } | |
2533 | ||
2534 | /* Generate code to push the regs specified in the mask, and return | |
2535 | the number of bytes the insns take. */ | |
2536 | ||
2537 | static void | |
1a95a963 JW |
2538 | push_regs (mask, mask2) |
2539 | int mask, mask2; | |
8aa2a305 JW |
2540 | { |
2541 | int i; | |
2542 | ||
1a95a963 | 2543 | for (i = 0; i < 32; i++) |
8aa2a305 JW |
2544 | if (mask & (1 << i)) |
2545 | push (i); | |
1a95a963 JW |
2546 | for (i = 32; i < FIRST_PSEUDO_REGISTER; i++) |
2547 | if (mask2 & (1 << (i - 32))) | |
2548 | push (i); | |
8aa2a305 JW |
2549 | } |
2550 | ||
2551 | /* Work out the registers which need to be saved, both as a mask and a | |
2552 | count. | |
2553 | ||
2554 | If doing a pragma interrupt function, then push all regs used by the | |
2555 | function, and if we call another function (we can tell by looking at PR), | |
2556 | make sure that all the regs it clobbers are safe too. */ | |
2557 | ||
2558 | static int | |
1a95a963 | 2559 | calc_live_regs (count_ptr, live_regs_mask2) |
8aa2a305 | 2560 | int *count_ptr; |
1a95a963 | 2561 | int *live_regs_mask2; |
8aa2a305 JW |
2562 | { |
2563 | int reg; | |
2564 | int live_regs_mask = 0; | |
2565 | int count = 0; | |
2566 | ||
1a95a963 | 2567 | *live_regs_mask2 = 0; |
8aa2a305 JW |
2568 | for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++) |
2569 | { | |
2570 | if (pragma_interrupt && ! pragma_trapa) | |
2571 | { | |
1a95a963 | 2572 | /* Need to save all the regs ever live. */ |
8aa2a305 | 2573 | if ((regs_ever_live[reg] |
20fef67b JW |
2574 | || (call_used_regs[reg] && ! fixed_regs[reg] |
2575 | && regs_ever_live[PR_REG]) | |
2576 | || reg == MACH_REG | |
2577 | || reg == MACL_REG) | |
8aa2a305 | 2578 | && reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM |
1a95a963 | 2579 | && reg != T_REG && reg != GBR_REG) |
8aa2a305 | 2580 | { |
1a95a963 JW |
2581 | if (reg >= 32) |
2582 | *live_regs_mask2 |= 1 << (reg - 32); | |
2583 | else | |
2584 | live_regs_mask |= 1 << reg; | |
8aa2a305 JW |
2585 | count++; |
2586 | } | |
2587 | } | |
2588 | else | |
2589 | { | |
2590 | /* Only push those regs which are used and need to be saved. */ | |
2591 | if (regs_ever_live[reg] && ! call_used_regs[reg]) | |
2592 | { | |
1a95a963 JW |
2593 | if (reg >= 32) |
2594 | *live_regs_mask2 |= 1 << (reg - 32); | |
2595 | else | |
2596 | live_regs_mask |= (1 << reg); | |
8aa2a305 JW |
2597 | count++; |
2598 | } | |
2599 | } | |
2600 | } | |
2601 | ||
2602 | *count_ptr = count; | |
2603 | return live_regs_mask; | |
2604 | } | |
2605 | ||
2606 | /* Code to generate prologue and epilogue sequences */ | |
b9654711 SC |
2607 | |
2608 | void | |
2609 | sh_expand_prologue () | |
2610 | { | |
2611 | int live_regs_mask; | |
40d2032b | 2612 | int d, i; |
1a95a963 JW |
2613 | int live_regs_mask2; |
2614 | live_regs_mask = calc_live_regs (&d, &live_regs_mask2); | |
b9654711 | 2615 | |
0d7e008e | 2616 | /* We have pretend args if we had an object sent partially in registers |
8aa2a305 | 2617 | and partially on the stack, e.g. a large structure. */ |
46d81ffa | 2618 | output_stack_adjust (-current_function_pretend_args_size, stack_pointer_rtx); |
b9654711 | 2619 | |
40d2032b JW |
2620 | extra_push = 0; |
2621 | ||
2622 | /* This is set by SETUP_VARARGS to indicate that this is a varargs | |
1a95a963 | 2623 | routine. Clear it here so that the next function isn't affected. */ |
b9654711 SC |
2624 | if (current_function_anonymous_args) |
2625 | { | |
40d2032b JW |
2626 | current_function_anonymous_args = 0; |
2627 | ||
1a95a963 JW |
2628 | /* This is not used by the SH3E calling convention */ |
2629 | if (!TARGET_SH3E) | |
2630 | { | |
2631 | /* Push arg regs as if they'd been provided by caller in stack. */ | |
2632 | for (i = 0; i < NPARM_REGS(SImode); i++) | |
2633 | { | |
2634 | int rn = NPARM_REGS(SImode) + FIRST_PARM_REG - i - 1; | |
2635 | if (i > (NPARM_REGS(SImode) | |
2636 | - current_function_args_info.arg_count[(int) SH_ARG_INT] | |
2637 | - current_function_varargs)) | |
2638 | break; | |
2639 | push (rn); | |
2640 | extra_push += 4; | |
2641 | } | |
2642 | } | |
b9654711 | 2643 | } |
1a95a963 JW |
2644 | |
2645 | push_regs (live_regs_mask, live_regs_mask2); | |
2646 | ||
46d81ffa | 2647 | output_stack_adjust (-get_frame_size (), stack_pointer_rtx); |
b9654711 SC |
2648 | |
2649 | if (frame_pointer_needed) | |
8aa2a305 | 2650 | emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx)); |
b9654711 SC |
2651 | } |
2652 | ||
2653 | void | |
2654 | sh_expand_epilogue () | |
2655 | { | |
2656 | int live_regs_mask; | |
40d2032b | 2657 | int d, i; |
b9654711 | 2658 | |
1a95a963 JW |
2659 | int live_regs_mask2; |
2660 | live_regs_mask = calc_live_regs (&d, &live_regs_mask2); | |
16bea517 | 2661 | |
b9654711 | 2662 | if (frame_pointer_needed) |
46d81ffa RK |
2663 | { |
2664 | /* We deliberately make the add dependent on the frame_pointer, | |
2665 | to ensure that instruction scheduling won't move the stack pointer | |
2666 | adjust before instructions reading from the frame. This can fail | |
2667 | if there is an interrupt which then writes to the stack. */ | |
2668 | output_stack_adjust (get_frame_size (), frame_pointer_rtx); | |
2669 | emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx)); | |
2670 | } | |
2671 | else | |
2672 | output_stack_adjust (get_frame_size (), stack_pointer_rtx); | |
b9654711 | 2673 | |
16bea517 | 2674 | /* Pop all the registers. */ |
0d7e008e | 2675 | |
b9654711 SC |
2676 | for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) |
2677 | { | |
2678 | int j = (FIRST_PSEUDO_REGISTER - 1) - i; | |
1a95a963 JW |
2679 | if (j < 32 && (live_regs_mask & (1 << j))) |
2680 | pop (j); | |
2681 | else if (j >= 32 && (live_regs_mask2 & (1 << (j - 32)))) | |
8aa2a305 | 2682 | pop (j); |
b9654711 | 2683 | } |
b9654711 | 2684 | |
46d81ffa RK |
2685 | output_stack_adjust (extra_push + current_function_pretend_args_size, |
2686 | stack_pointer_rtx); | |
b9654711 SC |
2687 | } |
2688 | ||
8aa2a305 JW |
2689 | /* Clear variables at function end. */ |
2690 | ||
2691 | void | |
2692 | function_epilogue (stream, size) | |
2693 | FILE *stream; | |
2694 | int size; | |
2695 | { | |
956a5206 | 2696 | pragma_interrupt = pragma_trapa = pragma_nosave_low_regs = 0; |
8aa2a305 JW |
2697 | } |
2698 | ||
1a95a963 JW |
2699 | rtx |
2700 | sh_builtin_saveregs (arglist) | |
2701 | tree arglist; | |
2702 | { | |
2703 | tree fntype = TREE_TYPE (current_function_decl); | |
2704 | /* First unnamed integer register. */ | |
2705 | int first_intreg = current_function_args_info.arg_count[(int) SH_ARG_INT]; | |
2706 | /* Number of integer registers we need to save. */ | |
2707 | int n_intregs = MAX (0, NPARM_REGS (SImode) - first_intreg); | |
2708 | /* First unnamed SFmode float reg */ | |
2709 | int first_floatreg = current_function_args_info.arg_count[(int) SH_ARG_FLOAT]; | |
2710 | /* Number of SFmode float regs to save. */ | |
2711 | int n_floatregs = MAX (0, NPARM_REGS (SFmode) - first_floatreg); | |
2712 | int ptrsize = GET_MODE_SIZE (Pmode); | |
2713 | rtx valist, regbuf, fpregs; | |
2714 | int bufsize, regno; | |
2715 | ||
2716 | /* Allocate block of memory for the regs. */ | |
2717 | /* ??? If n_intregs + n_floatregs == 0, should we allocate at least 1 byte? | |
2718 | Or can assign_stack_local accept a 0 SIZE argument? */ | |
2719 | bufsize = (n_intregs * UNITS_PER_WORD) + (n_floatregs * UNITS_PER_WORD); | |
2720 | ||
2721 | regbuf = assign_stack_local (BLKmode, bufsize, 0); | |
2722 | MEM_IN_STRUCT_P (regbuf) = 1; | |
2723 | ||
2724 | /* Save int args. | |
2725 | This is optimized to only save the regs that are necessary. Explicitly | |
2726 | named args need not be saved. */ | |
2727 | if (n_intregs > 0) | |
2728 | move_block_from_reg (BASE_ARG_REG (SImode) + first_intreg, | |
2729 | gen_rtx (MEM, BLKmode, | |
2730 | plus_constant (XEXP (regbuf, 0), | |
2731 | n_floatregs * UNITS_PER_WORD)), | |
2732 | n_intregs, n_intregs * UNITS_PER_WORD); | |
2733 | ||
2734 | /* Save float args. | |
2735 | This is optimized to only save the regs that are necessary. Explicitly | |
2736 | named args need not be saved. | |
2737 | We explicitly build a pointer to the buffer because it halves the insn | |
2738 | count when not optimizing (otherwise the pointer is built for each reg | |
2739 | saved). */ | |
2740 | ||
2741 | fpregs = gen_reg_rtx (Pmode); | |
2742 | emit_move_insn (fpregs, XEXP (regbuf, 0)); | |
2743 | for (regno = first_floatreg; regno < NPARM_REGS (SFmode); regno ++) | |
2744 | emit_move_insn (gen_rtx (MEM, SFmode, | |
2745 | plus_constant (fpregs, | |
2746 | GET_MODE_SIZE (SFmode) | |
2747 | * (regno - first_floatreg))), | |
2748 | gen_rtx (REG, SFmode, | |
2749 | BASE_ARG_REG (SFmode) + regno)); | |
2750 | ||
2751 | /* Return the address of the regbuf. */ | |
2752 | return XEXP (regbuf, 0); | |
2753 | } | |
2754 | ||
0d7e008e SC |
2755 | /* Define the offset between two registers, one to be eliminated, and |
2756 | the other its replacement, at the start of a routine. */ | |
2757 | ||
2758 | int | |
2759 | initial_elimination_offset (from, to) | |
8e87e161 SC |
2760 | int from; |
2761 | int to; | |
0d7e008e SC |
2762 | { |
2763 | int regs_saved; | |
0d7e008e SC |
2764 | int total_saved_regs_space; |
2765 | int total_auto_space = get_frame_size (); | |
8e87e161 | 2766 | |
2afeea0f JW |
2767 | int live_regs_mask, live_regs_mask2; |
2768 | live_regs_mask = calc_live_regs (®s_saved, &live_regs_mask2); | |
1a95a963 | 2769 | |
0d7e008e | 2770 | total_saved_regs_space = (regs_saved) * 4; |
b9654711 | 2771 | |
0d7e008e | 2772 | if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) |
8aa2a305 JW |
2773 | return total_saved_regs_space + total_auto_space; |
2774 | ||
0d7e008e | 2775 | if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) |
8aa2a305 JW |
2776 | return total_saved_regs_space + total_auto_space; |
2777 | ||
2778 | /* Initial gap between fp and sp is 0. */ | |
0d7e008e | 2779 | if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) |
8aa2a305 JW |
2780 | return 0; |
2781 | ||
2afeea0f JW |
2782 | if (from == RETURN_ADDRESS_POINTER_REGNUM |
2783 | && (to == FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM)) | |
2784 | { | |
2785 | int i, n = 0; | |
2786 | for (i = PR_REG+1; i < 32; i++) | |
2787 | if (live_regs_mask & (1 << i)) | |
2788 | n += 4; | |
2789 | for (i = 32; i < FIRST_PSEUDO_REGISTER; i++) | |
2790 | if (live_regs_mask2 & (1 << (i - 32))) | |
2791 | n += 4; | |
2792 | return n + total_auto_space; | |
2793 | } | |
2794 | ||
0d7e008e SC |
2795 | abort (); |
2796 | } | |
8aa2a305 | 2797 | \f |
0d7e008e | 2798 | /* Handle machine specific pragmas to be semi-compatible with Hitachi |
16bea517 | 2799 | compiler. */ |
b9654711 SC |
2800 | |
2801 | int | |
119d0c36 | 2802 | handle_pragma (file, t) |
0d7e008e | 2803 | FILE *file; |
119d0c36 | 2804 | tree t; |
b9654711 | 2805 | { |
119d0c36 JW |
2806 | int retval = 0; |
2807 | register char *pname; | |
b9654711 | 2808 | |
119d0c36 JW |
2809 | if (TREE_CODE (t) != IDENTIFIER_NODE) |
2810 | return 0; | |
05a81fe5 | 2811 | |
119d0c36 JW |
2812 | pname = IDENTIFIER_POINTER (t); |
2813 | if (strcmp (pname, "interrupt") == 0) | |
2814 | pragma_interrupt = retval = 1; | |
2815 | else if (strcmp (pname, "trapa") == 0) | |
2816 | pragma_interrupt = pragma_trapa = retval = 1; | |
2817 | else if (strcmp (pname, "nosave_low_regs") == 0) | |
2818 | pragma_nosave_low_regs = retval = 1; | |
05a81fe5 | 2819 | |
119d0c36 | 2820 | return retval; |
0d7e008e SC |
2821 | } |
2822 | \f | |
8aa2a305 | 2823 | /* Predicates used by the templates. */ |
0d7e008e | 2824 | |
8aa2a305 JW |
2825 | /* Returns 1 if OP is MACL, MACH or PR. The input must be a REG rtx. |
2826 | Used only in general_movsrc_operand. */ | |
0d7e008e | 2827 | |
8aa2a305 JW |
2828 | int |
2829 | system_reg_operand (op, mode) | |
2830 | rtx op; | |
2831 | enum machine_mode mode; | |
0d7e008e | 2832 | { |
8aa2a305 | 2833 | switch (REGNO (op)) |
0d7e008e | 2834 | { |
8aa2a305 JW |
2835 | case PR_REG: |
2836 | case MACL_REG: | |
2837 | case MACH_REG: | |
2838 | return 1; | |
0d7e008e | 2839 | } |
8aa2a305 | 2840 | return 0; |
0d7e008e | 2841 | } |
0d7e008e SC |
2842 | |
2843 | /* Returns 1 if OP can be source of a simple move operation. | |
2844 | Same as general_operand, but a LABEL_REF is valid, PRE_DEC is | |
16bea517 | 2845 | invalid as are subregs of system registers. */ |
0d7e008e SC |
2846 | |
2847 | int | |
2848 | general_movsrc_operand (op, mode) | |
2849 | rtx op; | |
2850 | enum machine_mode mode; | |
2851 | { | |
06c386ea SC |
2852 | if (GET_CODE (op) == MEM) |
2853 | { | |
2854 | rtx inside = XEXP (op, 0); | |
2855 | if (GET_CODE (inside) == CONST) | |
2856 | inside = XEXP (inside, 0); | |
0d7e008e | 2857 | |
06c386ea SC |
2858 | if (GET_CODE (inside) == LABEL_REF) |
2859 | return 1; | |
8e87e161 | 2860 | |
06c386ea | 2861 | if (GET_CODE (inside) == PLUS |
8aa2a305 JW |
2862 | && GET_CODE (XEXP (inside, 0)) == LABEL_REF |
2863 | && GET_CODE (XEXP (inside, 1)) == CONST_INT) | |
06c386ea | 2864 | return 1; |
16bea517 JW |
2865 | |
2866 | /* Only post inc allowed. */ | |
97f8690b | 2867 | if (GET_CODE (inside) == PRE_DEC) |
06c386ea | 2868 | return 0; |
06c386ea | 2869 | } |
0d7e008e SC |
2870 | |
2871 | if ((mode == QImode || mode == HImode) | |
2872 | && (GET_CODE (op) == SUBREG | |
2873 | && GET_CODE (XEXP (op, 0)) == REG | |
2874 | && system_reg_operand (XEXP (op, 0), mode))) | |
2875 | return 0; | |
2876 | ||
0d7e008e | 2877 | return general_operand (op, mode); |
b9654711 SC |
2878 | } |
2879 | ||
0d7e008e SC |
2880 | /* Returns 1 if OP can be a destination of a move. |
2881 | Same as general_operand, but no preinc allowed. */ | |
2882 | ||
b9654711 | 2883 | int |
0d7e008e SC |
2884 | general_movdst_operand (op, mode) |
2885 | rtx op; | |
2886 | enum machine_mode mode; | |
b9654711 | 2887 | { |
16bea517 | 2888 | /* Only pre dec allowed. */ |
97f8690b | 2889 | if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC) |
0d7e008e | 2890 | return 0; |
d3ae8277 | 2891 | |
0d7e008e SC |
2892 | return general_operand (op, mode); |
2893 | } | |
2894 | ||
0d7e008e SC |
2895 | /* Returns 1 if OP is a normal arithmetic register. */ |
2896 | ||
2897 | int | |
2898 | arith_reg_operand (op, mode) | |
2899 | rtx op; | |
2900 | enum machine_mode mode; | |
2901 | { | |
2902 | if (register_operand (op, mode)) | |
2903 | { | |
519164a9 JW |
2904 | int regno; |
2905 | ||
0d7e008e | 2906 | if (GET_CODE (op) == REG) |
519164a9 JW |
2907 | regno = REGNO (op); |
2908 | else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG) | |
2909 | regno = REGNO (SUBREG_REG (op)); | |
2910 | else | |
2911 | return 1; | |
2912 | ||
2913 | return (regno != T_REG && regno != PR_REG && regno != FPUL_REG | |
2914 | && regno != MACH_REG && regno != MACL_REG); | |
0d7e008e SC |
2915 | } |
2916 | return 0; | |
2917 | } | |
2918 | ||
0d7e008e SC |
2919 | /* Returns 1 if OP is a valid source operand for an arithmetic insn. */ |
2920 | ||
2921 | int | |
2922 | arith_operand (op, mode) | |
2923 | rtx op; | |
2924 | enum machine_mode mode; | |
2925 | { | |
2926 | if (arith_reg_operand (op, mode)) | |
2927 | return 1; | |
2928 | ||
8aa2a305 JW |
2929 | if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I (INTVAL (op))) |
2930 | return 1; | |
2931 | ||
0d7e008e SC |
2932 | return 0; |
2933 | } | |
2934 | ||
22e1ebf1 JW |
2935 | /* Returns 1 if OP is a valid source operand for a compare insn. */ |
2936 | ||
2937 | int | |
2938 | arith_reg_or_0_operand (op, mode) | |
2939 | rtx op; | |
2940 | enum machine_mode mode; | |
2941 | { | |
2942 | if (arith_reg_operand (op, mode)) | |
2943 | return 1; | |
2944 | ||
8aa2a305 JW |
2945 | if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_N (INTVAL (op))) |
2946 | return 1; | |
2947 | ||
22e1ebf1 JW |
2948 | return 0; |
2949 | } | |
2950 | ||
16bea517 | 2951 | /* Returns 1 if OP is a valid source operand for a logical operation. */ |
0d7e008e SC |
2952 | |
2953 | int | |
2954 | logical_operand (op, mode) | |
2955 | rtx op; | |
2956 | enum machine_mode mode; | |
2957 | { | |
2958 | if (arith_reg_operand (op, mode)) | |
2959 | return 1; | |
2960 | ||
8aa2a305 JW |
2961 | if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_L (INTVAL (op))) |
2962 | return 1; | |
2963 | ||
0d7e008e | 2964 | return 0; |
b9654711 | 2965 | } |
d3ae8277 | 2966 | |
1a95a963 JW |
2967 | /* Nonzero if OP is a floating point value with value 0.0. */ |
2968 | ||
2969 | int | |
2970 | fp_zero_operand (op) | |
2971 | rtx op; | |
d3ae8277 | 2972 | { |
1a95a963 | 2973 | REAL_VALUE_TYPE r; |
d3ae8277 | 2974 | |
1a95a963 JW |
2975 | if (GET_MODE (op) != SFmode) |
2976 | return 0; | |
2977 | ||
2978 | REAL_VALUE_FROM_CONST_DOUBLE (r, op); | |
e4fa6b06 | 2979 | return REAL_VALUES_EQUAL (r, dconst0) && ! REAL_VALUE_MINUS_ZERO (r); |
d3ae8277 SC |
2980 | } |
2981 | ||
1a95a963 | 2982 | /* Nonzero if OP is a floating point value with value 1.0. */ |
d3ae8277 SC |
2983 | |
2984 | int | |
1a95a963 JW |
2985 | fp_one_operand (op) |
2986 | rtx op; | |
d3ae8277 | 2987 | { |
1a95a963 JW |
2988 | REAL_VALUE_TYPE r; |
2989 | ||
2990 | if (GET_MODE (op) != SFmode) | |
2991 | return 0; | |
2992 | ||
2993 | REAL_VALUE_FROM_CONST_DOUBLE (r, op); | |
2994 | return REAL_VALUES_EQUAL (r, dconst1); | |
d3ae8277 | 2995 | } |
a55e9d2b RK |
2996 | \f |
2997 | /* Return non-zero if REG is not used after INSN. | |
2998 | We assume REG is a reload reg, and therefore does | |
8b760293 | 2999 | not live past labels. It may live past calls or jumps though. */ |
a55e9d2b RK |
3000 | int |
3001 | reg_unused_after (reg, insn) | |
3002 | rtx reg; | |
3003 | rtx insn; | |
3004 | { | |
8783b15e | 3005 | enum rtx_code code; |
a55e9d2b RK |
3006 | rtx set; |
3007 | ||
3008 | /* If the reg is set by this instruction, then it is safe for our | |
3009 | case. Disregard the case where this is a store to memory, since | |
3010 | we are checking a register used in the store address. */ | |
3011 | set = single_set (insn); | |
3012 | if (set && GET_CODE (SET_DEST (set)) != MEM | |
3013 | && reg_overlap_mentioned_p (reg, SET_DEST (set))) | |
3014 | return 1; | |
3015 | ||
3016 | while (insn = NEXT_INSN (insn)) | |
3017 | { | |
a55e9d2b | 3018 | code = GET_CODE (insn); |
8783b15e | 3019 | |
c8f6f18d RK |
3020 | #if 0 |
3021 | /* If this is a label that existed before reload, then the register | |
3022 | if dead here. However, if this is a label added by reorg, then | |
3023 | the register may still be live here. We can't tell the difference, | |
3024 | so we just ignore labels completely. */ | |
8783b15e | 3025 | if (code == CODE_LABEL) |
a55e9d2b | 3026 | return 1; |
c8f6f18d RK |
3027 | /* else */ |
3028 | #endif | |
a55e9d2b | 3029 | |
8b760293 JW |
3030 | if (code == JUMP_INSN) |
3031 | return 0; | |
3032 | ||
8783b15e RK |
3033 | /* If this is a sequence, we must handle them all at once. |
3034 | We could have for instance a call that sets the target register, | |
3035 | and a insn in a delay slot that uses the register. In this case, | |
3036 | we must return 0. */ | |
8b760293 | 3037 | else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE) |
a55e9d2b | 3038 | { |
8783b15e RK |
3039 | int i; |
3040 | int retval = 0; | |
3041 | ||
3042 | for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) | |
3043 | { | |
3044 | rtx this_insn = XVECEXP (PATTERN (insn), 0, i); | |
3045 | rtx set = single_set (this_insn); | |
3046 | ||
3047 | if (GET_CODE (this_insn) == CALL_INSN) | |
3048 | code = CALL_INSN; | |
38f35781 JW |
3049 | else if (GET_CODE (this_insn) == JUMP_INSN) |
3050 | { | |
3051 | if (INSN_ANNULLED_BRANCH_P (this_insn)) | |
3052 | return 0; | |
3053 | code = JUMP_INSN; | |
3054 | } | |
a55e9d2b | 3055 | |
8783b15e RK |
3056 | if (set && reg_overlap_mentioned_p (reg, SET_SRC (set))) |
3057 | return 0; | |
3058 | if (set && reg_overlap_mentioned_p (reg, SET_DEST (set))) | |
3059 | { | |
3060 | if (GET_CODE (SET_DEST (set)) != MEM) | |
3061 | retval = 1; | |
3062 | else | |
3063 | return 0; | |
3064 | } | |
3065 | if (set == 0 | |
3066 | && reg_overlap_mentioned_p (reg, PATTERN (this_insn))) | |
3067 | return 0; | |
3068 | } | |
3069 | if (retval == 1) | |
3070 | return 1; | |
38f35781 JW |
3071 | else if (code == JUMP_INSN) |
3072 | return 0; | |
8783b15e RK |
3073 | } |
3074 | else if (GET_RTX_CLASS (code) == 'i') | |
a55e9d2b RK |
3075 | { |
3076 | rtx set = single_set (insn); | |
3077 | ||
3078 | if (set && reg_overlap_mentioned_p (reg, SET_SRC (set))) | |
3079 | return 0; | |
3080 | if (set && reg_overlap_mentioned_p (reg, SET_DEST (set))) | |
3081 | return GET_CODE (SET_DEST (set)) != MEM; | |
3082 | if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn))) | |
3083 | return 0; | |
3084 | } | |
8783b15e RK |
3085 | |
3086 | if (code == CALL_INSN && call_used_regs[REGNO (reg)]) | |
3087 | return 1; | |
a55e9d2b RK |
3088 | } |
3089 | return 1; | |
3090 | } |