]>
Commit | Line | Data |
---|---|---|
16bea517 | 1 | /* Output routines for GCC for Hitachi Super-H. |
8aa2a305 | 2 | Copyright (C) 1993, 1994, 1995 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" | |
bc45ade3 | 36 | |
00f8ff66 SC |
37 | #define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0) |
38 | #define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1) | |
39 | ||
20b04867 | 40 | /* ??? The pragma interrupt support will not work for SH3. */ |
8aa2a305 JW |
41 | /* This is set by #pragma interrupt and #pragma trapa, and causes gcc to |
42 | output code for the next function appropriate for an interrupt handler. */ | |
0d7e008e | 43 | int pragma_interrupt; |
bc45ade3 | 44 | |
8aa2a305 JW |
45 | /* This is set by #pragma trapa, and is similar to the above, except that |
46 | the compiler doesn't emit code to preserve all registers. */ | |
47 | static int pragma_trapa; | |
48 | ||
49 | /* This is used for communication between SETUP_INCOMING_VARARGS and | |
50 | sh_expand_prologue. */ | |
bc45ade3 | 51 | int current_function_anonymous_args; |
16bea517 | 52 | |
8aa2a305 JW |
53 | /* Global variables from toplev.c and final.c that are used within, but |
54 | not declared in any header file. */ | |
b9654711 | 55 | extern char *version_string; |
8aa2a305 | 56 | extern int *insn_addresses; |
00f8ff66 | 57 | |
bc45ade3 SC |
58 | /* Global variables for machine-dependent things. */ |
59 | ||
16bea517 JW |
60 | /* Which cpu are we scheduling for. */ |
61 | enum processor_type sh_cpu; | |
62 | ||
bc45ade3 | 63 | /* Saved operands from the last compare to use when we generate an scc |
16bea517 | 64 | or bcc insn. */ |
bc45ade3 SC |
65 | |
66 | rtx sh_compare_op0; | |
67 | rtx sh_compare_op1; | |
68 | ||
69 | /* Provides the class number of the smallest class containing | |
16bea517 | 70 | reg number. */ |
bc45ade3 SC |
71 | |
72 | int regno_reg_class[FIRST_PSEUDO_REGISTER] = | |
73 | { | |
8e87e161 | 74 | R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, |
bc45ade3 SC |
75 | GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, |
76 | GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, | |
77 | GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, | |
8e87e161 SC |
78 | GENERAL_REGS, PR_REGS, T_REGS, NO_REGS, |
79 | MAC_REGS, MAC_REGS, | |
bc45ade3 SC |
80 | }; |
81 | ||
82 | /* Provide reg_class from a letter such as appears in the machine | |
16bea517 | 83 | description. */ |
bc45ade3 SC |
84 | |
85 | enum reg_class reg_class_from_letter[] = | |
86 | { | |
87 | /* a */ NO_REGS, /* b */ NO_REGS, /* c */ NO_REGS, /* d */ NO_REGS, | |
88 | /* e */ NO_REGS, /* f */ NO_REGS, /* g */ NO_REGS, /* h */ NO_REGS, | |
89 | /* i */ NO_REGS, /* j */ NO_REGS, /* k */ NO_REGS, /* l */ PR_REGS, | |
90 | /* m */ NO_REGS, /* n */ NO_REGS, /* o */ NO_REGS, /* p */ NO_REGS, | |
91 | /* q */ NO_REGS, /* r */ NO_REGS, /* s */ NO_REGS, /* t */ T_REGS, | |
92 | /* u */ NO_REGS, /* v */ NO_REGS, /* w */ NO_REGS, /* x */ MAC_REGS, | |
93 | /* y */ NO_REGS, /* z */ R0_REGS | |
94 | }; | |
b9654711 | 95 | \f |
16bea517 | 96 | /* Print the operand address in x to the stream. */ |
bc45ade3 SC |
97 | |
98 | void | |
99 | print_operand_address (stream, x) | |
100 | FILE *stream; | |
101 | rtx x; | |
102 | { | |
103 | switch (GET_CODE (x)) | |
104 | { | |
105 | case REG: | |
106 | fprintf (stream, "@%s", reg_names[REGNO (x)]); | |
107 | break; | |
8aa2a305 | 108 | |
bc45ade3 SC |
109 | case PLUS: |
110 | { | |
111 | rtx base = XEXP (x, 0); | |
112 | rtx index = XEXP (x, 1); | |
113 | ||
bc45ade3 SC |
114 | switch (GET_CODE (index)) |
115 | { | |
116 | case CONST_INT: | |
8aa2a305 | 117 | fprintf (stream, "@(%d,%s)", INTVAL (index), |
bc45ade3 SC |
118 | reg_names[REGNO (base)]); |
119 | break; | |
120 | ||
121 | case REG: | |
b9654711 SC |
122 | fprintf (stream, "@(r0,%s)", |
123 | reg_names[MAX (REGNO (base), REGNO (index))]); | |
bc45ade3 SC |
124 | break; |
125 | ||
126 | default: | |
b9654711 | 127 | debug_rtx (x); |
bc45ade3 SC |
128 | abort (); |
129 | } | |
130 | } | |
bc45ade3 | 131 | break; |
8aa2a305 | 132 | |
bc45ade3 SC |
133 | case PRE_DEC: |
134 | fprintf (stream, "@-%s", reg_names[REGNO (XEXP (x, 0))]); | |
135 | break; | |
136 | ||
137 | case POST_INC: | |
138 | fprintf (stream, "@%s+", reg_names[REGNO (XEXP (x, 0))]); | |
139 | break; | |
140 | ||
141 | default: | |
142 | output_addr_const (stream, x); | |
143 | break; | |
144 | } | |
145 | } | |
146 | ||
147 | /* Print operand x (an rtx) in assembler syntax to file stream | |
148 | according to modifier code. | |
149 | ||
b9654711 | 150 | '.' print a .s if insn needs delay slot |
d3ae8277 | 151 | '@' print rte or rts depending upon pragma interruptness |
8aa2a305 JW |
152 | '#' output a nop if there is nothing to put in the delay slot |
153 | 'O' print a constant without the # | |
00f8ff66 | 154 | 'R' print the LSW of a dp value - changes if in little endian |
00f8ff66 | 155 | 'S' print the MSW of a dp value - changes if in little endian |
8aa2a305 | 156 | 'T' print the next word of a dp value - same as 'R' in big endian mode. */ |
bc45ade3 SC |
157 | |
158 | void | |
159 | print_operand (stream, x, code) | |
160 | FILE *stream; | |
161 | rtx x; | |
162 | int code; | |
163 | { | |
164 | switch (code) | |
165 | { | |
b9654711 | 166 | case '.': |
79b2746a JW |
167 | if (final_sequence |
168 | && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) | |
b9654711 SC |
169 | fprintf (stream, ".s"); |
170 | break; | |
d3ae8277 SC |
171 | case '@': |
172 | if (pragma_interrupt) | |
8e87e161 | 173 | fprintf (stream, "rte"); |
d3ae8277 | 174 | else |
8e87e161 | 175 | fprintf (stream, "rts"); |
d3ae8277 | 176 | break; |
bc45ade3 | 177 | case '#': |
16bea517 | 178 | /* Output a nop if there's nothing in the delay slot. */ |
bc45ade3 | 179 | if (dbr_sequence_length () == 0) |
8aa2a305 | 180 | fprintf (stream, "\n\tnop"); |
bc45ade3 | 181 | break; |
b9654711 | 182 | case 'O': |
0d7e008e | 183 | output_addr_const (stream, x); |
bc45ade3 | 184 | break; |
bc45ade3 | 185 | case 'R': |
8aa2a305 JW |
186 | fputs (reg_names[REGNO (x) + LSW], (stream)); |
187 | break; | |
188 | case 'S': | |
189 | fputs (reg_names[REGNO (x) + MSW], (stream)); | |
00f8ff66 SC |
190 | break; |
191 | case 'T': | |
16bea517 | 192 | /* Next word of a double. */ |
bc45ade3 SC |
193 | switch (GET_CODE (x)) |
194 | { | |
195 | case REG: | |
196 | fputs (reg_names[REGNO (x) + 1], (stream)); | |
197 | break; | |
198 | case MEM: | |
8aa2a305 JW |
199 | print_operand_address (stream, |
200 | XEXP (adj_offsettable_operand (x, 4), 0)); | |
bc45ade3 SC |
201 | break; |
202 | } | |
203 | break; | |
bc45ade3 SC |
204 | default: |
205 | switch (GET_CODE (x)) | |
206 | { | |
207 | case REG: | |
208 | fputs (reg_names[REGNO (x)], (stream)); | |
209 | break; | |
210 | case MEM: | |
211 | output_address (XEXP (x, 0)); | |
212 | break; | |
213 | default: | |
214 | fputc ('#', stream); | |
215 | output_addr_const (stream, x); | |
216 | break; | |
bc45ade3 SC |
217 | } |
218 | break; | |
219 | } | |
220 | } | |
bc45ade3 | 221 | \f |
0d7e008e SC |
222 | /* Emit code to perform a block move. Choose the best method. |
223 | ||
224 | OPERANDS[0] is the destination. | |
225 | OPERANDS[1] is the source. | |
226 | OPERANDS[2] is the size. | |
227 | OPERANDS[3] is the alignment safe to use. */ | |
228 | ||
0d7e008e SC |
229 | int |
230 | expand_block_move (operands) | |
231 | rtx *operands; | |
232 | { | |
233 | int align = INTVAL (operands[3]); | |
234 | int constp = (GET_CODE (operands[2]) == CONST_INT); | |
235 | int bytes = (constp ? INTVAL (operands[2]) : 0); | |
0d7e008e | 236 | |
8aa2a305 JW |
237 | /* If it isn't a constant number of bytes, or if it doesn't have 4 byte |
238 | alignment, or if it isn't a multiple of 4 bytes, then fail. */ | |
239 | if (! constp || align < 4 || (bytes % 4 != 0)) | |
d3ae8277 SC |
240 | return 0; |
241 | ||
8aa2a305 | 242 | if (bytes < 64) |
0d7e008e SC |
243 | { |
244 | char entry[30]; | |
245 | tree entry_name; | |
246 | rtx func_addr_rtx; | |
247 | rtx r4 = gen_rtx (REG, SImode, 4); | |
248 | rtx r5 = gen_rtx (REG, SImode, 5); | |
8aa2a305 JW |
249 | |
250 | sprintf (entry, "__movstrSI%d", bytes); | |
0d7e008e SC |
251 | entry_name = get_identifier (entry); |
252 | ||
8aa2a305 JW |
253 | func_addr_rtx |
254 | = copy_to_mode_reg (Pmode, | |
255 | gen_rtx (SYMBOL_REF, Pmode, | |
256 | IDENTIFIER_POINTER (entry_name))); | |
0d7e008e SC |
257 | emit_insn (gen_move_insn (r4, XEXP (operands[0], 0))); |
258 | emit_insn (gen_move_insn (r5, XEXP (operands[1], 0))); | |
259 | emit_insn (gen_block_move_real (func_addr_rtx)); | |
260 | return 1; | |
261 | } | |
8aa2a305 JW |
262 | |
263 | /* This is the same number of bytes as a memcpy call, but to a different | |
264 | less common function name, so this will occasionally use more space. */ | |
265 | if (! TARGET_SMALLCODE) | |
0d7e008e | 266 | { |
0d7e008e SC |
267 | tree entry_name; |
268 | rtx func_addr_rtx; | |
8aa2a305 | 269 | int final_switch, while_loop; |
0d7e008e SC |
270 | rtx r4 = gen_rtx (REG, SImode, 4); |
271 | rtx r5 = gen_rtx (REG, SImode, 5); | |
272 | rtx r6 = gen_rtx (REG, SImode, 6); | |
0d7e008e | 273 | |
8aa2a305 JW |
274 | entry_name = get_identifier ("__movstr"); |
275 | func_addr_rtx | |
276 | = copy_to_mode_reg (Pmode, | |
277 | gen_rtx (SYMBOL_REF, Pmode, | |
278 | IDENTIFIER_POINTER (entry_name))); | |
0d7e008e SC |
279 | emit_insn (gen_move_insn (r4, XEXP (operands[0], 0))); |
280 | emit_insn (gen_move_insn (r5, XEXP (operands[1], 0))); | |
281 | ||
8aa2a305 JW |
282 | /* r6 controls the size of the move. 16 is decremented from it |
283 | for each 64 bytes moved. Then the negative bit left over is used | |
284 | as an index into a list of move instructions. e.g., a 72 byte move | |
285 | would be set up with size(r6) = 14, for one iteration through the | |
286 | big while loop, and a switch of -2 for the last part. */ | |
0d7e008e | 287 | |
8aa2a305 JW |
288 | final_switch = 16 - ((bytes / 4) % 16); |
289 | while_loop = ((bytes / 4) / 16 - 1) * 16; | |
290 | emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch))); | |
291 | emit_insn (gen_block_lump_real (func_addr_rtx)); | |
292 | return 1; | |
0d7e008e | 293 | } |
0d7e008e | 294 | |
d3ae8277 | 295 | return 0; |
0d7e008e SC |
296 | } |
297 | ||
bc45ade3 | 298 | /* Prepare operands for a move define_expand; specifically, one of the |
8aa2a305 | 299 | operands must be in a register. */ |
bc45ade3 | 300 | |
b9654711 | 301 | int |
bc45ade3 SC |
302 | prepare_move_operands (operands, mode) |
303 | rtx operands[]; | |
304 | enum machine_mode mode; | |
305 | { | |
8aa2a305 JW |
306 | /* Copy the source to a register if both operands aren't registers. */ |
307 | if (! reload_in_progress && ! reload_completed | |
308 | && ! register_operand (operands[0], mode) | |
309 | && ! register_operand (operands[1], mode)) | |
310 | operands[1] = copy_to_mode_reg (mode, operands[1]); | |
311 | ||
312 | return 0; | |
313 | } | |
314 | ||
315 | /* Prepare the operands for an scc instruction; make sure that the | |
316 | compare has been done. */ | |
317 | rtx | |
318 | prepare_scc_operands (code) | |
319 | enum rtx_code code; | |
320 | { | |
321 | rtx t_reg = gen_rtx (REG, SImode, T_REG); | |
322 | enum rtx_code oldcode = code; | |
323 | ||
324 | /* First need a compare insn. */ | |
325 | switch (code) | |
bc45ade3 | 326 | { |
8aa2a305 JW |
327 | case NE: |
328 | /* It isn't possible to handle this case. */ | |
329 | abort (); | |
330 | case LT: | |
331 | code = GT; | |
332 | break; | |
333 | case LE: | |
334 | code = GE; | |
335 | break; | |
336 | case LTU: | |
337 | code = GTU; | |
338 | break; | |
339 | case LEU: | |
340 | code = GEU; | |
341 | break; | |
bc45ade3 | 342 | } |
8aa2a305 | 343 | if (code != oldcode) |
b9654711 | 344 | { |
8aa2a305 JW |
345 | rtx tmp = sh_compare_op0; |
346 | sh_compare_op0 = sh_compare_op1; | |
347 | sh_compare_op1 = tmp; | |
0d7e008e | 348 | } |
b9654711 | 349 | |
8aa2a305 JW |
350 | sh_compare_op0 = force_reg (SImode, sh_compare_op0); |
351 | if (code != EQ && code != NE | |
352 | && (sh_compare_op1 != const0_rtx | |
353 | || code == GTU || code == GEU || code == LTU || code == LEU)) | |
354 | sh_compare_op1 = force_reg (SImode, sh_compare_op1); | |
0d7e008e | 355 | |
8aa2a305 JW |
356 | emit_insn (gen_rtx (SET, VOIDmode, t_reg, |
357 | gen_rtx (code, SImode, sh_compare_op0, | |
358 | sh_compare_op1))); | |
0d7e008e | 359 | |
8aa2a305 | 360 | return t_reg; |
bc45ade3 SC |
361 | } |
362 | ||
8aa2a305 JW |
363 | /* Called from the md file, set up the operands of a compare instruction. */ |
364 | ||
365 | void | |
366 | from_compare (operands, code) | |
367 | rtx *operands; | |
8e87e161 | 368 | int code; |
bc45ade3 | 369 | { |
8aa2a305 | 370 | if (code != EQ && code != NE) |
bc45ade3 | 371 | { |
8aa2a305 | 372 | /* Force args into regs, since we can't use constants here. */ |
0d7e008e | 373 | sh_compare_op0 = force_reg (SImode, sh_compare_op0); |
8aa2a305 JW |
374 | if (sh_compare_op1 != const0_rtx |
375 | || code == GTU || code == GEU || code == LTU || code == LEU) | |
22e1ebf1 | 376 | sh_compare_op1 = force_reg (SImode, sh_compare_op1); |
bc45ade3 | 377 | } |
8aa2a305 JW |
378 | operands[1] = sh_compare_op0; |
379 | operands[2] = sh_compare_op1; | |
bc45ade3 SC |
380 | } |
381 | \f | |
16bea517 | 382 | /* Functions to output assembly code. */ |
bc45ade3 | 383 | |
b9654711 | 384 | /* Return a sequence of instructions to perform DI or DF move. |
bc45ade3 | 385 | |
b9654711 | 386 | Since the SH cannot move a DI or DF in one instruction, we have |
16bea517 | 387 | to take care when we see overlapping source and dest registers. */ |
0d7e008e | 388 | |
bc45ade3 | 389 | char * |
0d7e008e SC |
390 | output_movedouble (insn, operands, mode) |
391 | rtx insn; | |
bc45ade3 SC |
392 | rtx operands[]; |
393 | enum machine_mode mode; | |
394 | { | |
b9654711 SC |
395 | rtx dst = operands[0]; |
396 | rtx src = operands[1]; | |
b9654711 | 397 | |
0d7e008e | 398 | if (GET_CODE (dst) == MEM |
16bea517 | 399 | && GET_CODE (XEXP (dst, 0)) == PRE_DEC) |
8aa2a305 JW |
400 | return "mov.l %T1,%0\n\tmov.l %1,%0"; |
401 | ||
b9654711 SC |
402 | if (register_operand (dst, mode) |
403 | && register_operand (src, mode)) | |
bc45ade3 | 404 | { |
b9654711 | 405 | if (REGNO (src) == MACH_REG) |
00f8ff66 | 406 | return "sts mach,%S0\n\tsts macl,%R0"; |
bc45ade3 | 407 | |
8aa2a305 JW |
408 | /* When mov.d r1,r2 do r2->r3 then r1->r2; |
409 | when mov.d r1,r0 do r1->r0 then r2->r1. */ | |
b9654711 SC |
410 | |
411 | if (REGNO (src) + 1 == REGNO (dst)) | |
5325c0fa | 412 | return "mov %T1,%T0\n\tmov %1,%0"; |
b9654711 | 413 | else |
5325c0fa | 414 | return "mov %1,%0\n\tmov %T1,%T0"; |
b9654711 SC |
415 | } |
416 | else if (GET_CODE (src) == CONST_INT) | |
bc45ade3 | 417 | { |
8aa2a305 JW |
418 | if (INTVAL (src) < 0) |
419 | output_asm_insn ("mov #-1,%S0", operands); | |
bc45ade3 | 420 | else |
8aa2a305 | 421 | output_asm_insn ("mov #0,%S0", operands); |
bc45ade3 | 422 | |
8aa2a305 | 423 | return "mov %1,%R0"; |
0d7e008e | 424 | } |
b9654711 | 425 | else if (GET_CODE (src) == MEM) |
bc45ade3 | 426 | { |
8aa2a305 | 427 | int ptrreg = -1; |
b9654711 SC |
428 | int dreg = REGNO (dst); |
429 | rtx inside = XEXP (src, 0); | |
bc45ade3 SC |
430 | |
431 | if (GET_CODE (inside) == REG) | |
8aa2a305 | 432 | ptrreg = REGNO (inside); |
79b2746a JW |
433 | else if (GET_CODE (inside) == SUBREG) |
434 | ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside); | |
bc45ade3 SC |
435 | else if (GET_CODE (inside) == PLUS) |
436 | { | |
8aa2a305 JW |
437 | ptrreg = REGNO (XEXP (inside, 0)); |
438 | /* ??? A r0+REG address shouldn't be possible here, because it isn't | |
439 | an offsettable address. Unfortunately, offsettable addresses use | |
440 | QImode to check the offset, and a QImode offsettable address | |
441 | requires r0 for the other operand, which is not currently | |
442 | supported, so we can't use the 'o' constraint. | |
443 | Thus we must check for and handle r0+REG addresses here. | |
444 | We punt for now, since this is likely very rare. */ | |
445 | if (GET_CODE (XEXP (inside, 1)) == REG) | |
446 | abort (); | |
bc45ade3 | 447 | } |
0d7e008e | 448 | else if (GET_CODE (inside) == LABEL_REF) |
8aa2a305 | 449 | return "mov.l %1,%0\n\tmov.l %1+4,%T0"; |
8e87e161 | 450 | else if (GET_CODE (inside) == POST_INC) |
8aa2a305 | 451 | return "mov.l %1,%0\n\tmov.l %1,%T0"; |
bc45ade3 SC |
452 | else |
453 | abort (); | |
454 | ||
8aa2a305 JW |
455 | /* Work out the safe way to copy. Copy into the second half first. */ |
456 | if (dreg == ptrreg) | |
457 | return "mov.l %T1,%T0\n\tmov.l %1,%0"; | |
bc45ade3 SC |
458 | } |
459 | ||
00f8ff66 | 460 | return "mov.l %1,%0\n\tmov.l %T1,%T0"; |
bc45ade3 SC |
461 | } |
462 | ||
8aa2a305 JW |
463 | /* Print an instruction which would have gone into a delay slot after |
464 | another instruction, but couldn't because the other instruction expanded | |
465 | into a sequence where putting the slot insn at the end wouldn't work. */ | |
0d7e008e | 466 | |
8aa2a305 JW |
467 | static void |
468 | print_slot (insn) | |
469 | rtx insn; | |
470 | { | |
471 | final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file, optimize, 0, 1); | |
b9654711 | 472 | |
8aa2a305 JW |
473 | INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1; |
474 | } | |
0d7e008e | 475 | |
8aa2a305 JW |
476 | /* We can't tell if we need a register as a scratch for the jump |
477 | until after branch shortening, and then it's too late to allocate a | |
478 | register the 'proper' way. These instruction sequences are rare | |
479 | anyway, so to avoid always using a reg up from our limited set, we'll | |
480 | grab one when we need one on output. */ | |
0d7e008e | 481 | |
8aa2a305 JW |
482 | /* ??? Should fix compiler so that using a clobber scratch in jump |
483 | instructions works, and then this will be unnecessary. */ | |
0d7e008e SC |
484 | |
485 | char * | |
486 | output_far_jump (insn, op) | |
487 | rtx insn; | |
488 | rtx op; | |
489 | { | |
490 | rtx thislab = gen_label_rtx (); | |
491 | ||
8aa2a305 | 492 | /* Output the delay slot insn first if any. */ |
0d7e008e | 493 | if (dbr_sequence_length ()) |
8aa2a305 | 494 | print_slot (final_sequence); |
b9654711 | 495 | |
8aa2a305 JW |
496 | output_asm_insn ("mov.l r13,@-r15", 0); |
497 | output_asm_insn ("mov.l %O0,r13", &thislab); | |
498 | output_asm_insn ("jmp @r13", 0); | |
499 | output_asm_insn ("mov.l @r15+,r13", 0); | |
0d7e008e | 500 | output_asm_insn (".align 2", 0); |
d3ae8277 | 501 | ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (thislab)); |
0d7e008e SC |
502 | output_asm_insn (".long %O0", &op); |
503 | return ""; | |
504 | } | |
bc45ade3 | 505 | |
8aa2a305 JW |
506 | /* Local label counter, used for constants in the pool and inside |
507 | pattern branches. */ | |
508 | ||
509 | static int lf = 100; | |
510 | ||
511 | /* Output code for ordinary branches. */ | |
512 | ||
bc45ade3 | 513 | char * |
8aa2a305 | 514 | output_branch (logic, insn, operands) |
bc45ade3 | 515 | int logic; |
b9654711 | 516 | rtx insn; |
8aa2a305 | 517 | rtx *operands; |
bc45ade3 | 518 | { |
bc45ade3 | 519 | int label = lf++; |
8e87e161 | 520 | |
bc45ade3 SC |
521 | switch (get_attr_length (insn)) |
522 | { | |
523 | case 2: | |
22e1ebf1 JW |
524 | /* A branch with an unfilled delay slot. */ |
525 | case 4: | |
526 | /* Simple branch in range -252..+258 bytes */ | |
b9654711 | 527 | return logic ? "bt%. %l0" : "bf%. %l0"; |
bc45ade3 SC |
528 | |
529 | case 6: | |
22e1ebf1 JW |
530 | /* A branch with an unfilled delay slot. */ |
531 | case 8: | |
16bea517 | 532 | /* Branch in range -4092..+4098 bytes. */ |
b9654711 | 533 | { |
8aa2a305 JW |
534 | /* The call to print_slot will clobber the operands. */ |
535 | rtx op0 = operands[0]; | |
b9654711 | 536 | |
79b2746a JW |
537 | /* If the instruction in the delay slot is annulled (true), then |
538 | there is no delay slot where we can put it now. The only safe | |
539 | place for it is after the label. */ | |
540 | ||
16bea517 | 541 | if (final_sequence) |
b9654711 | 542 | { |
79b2746a JW |
543 | fprintf (asm_out_file, "\tb%c%s\tLF%d\n", logic ? 'f' : 't', |
544 | INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)) | |
545 | ? "" : ".s", label); | |
546 | if (! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) | |
547 | print_slot (final_sequence); | |
b9654711 | 548 | } |
b9654711 | 549 | else |
8aa2a305 | 550 | fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label); |
b9654711 | 551 | |
8aa2a305 JW |
552 | output_asm_insn ("bra %l0", &op0); |
553 | fprintf (asm_out_file, "\tnop\n"); | |
b9654711 | 554 | fprintf (asm_out_file, "LF%d:\n", label); |
79b2746a JW |
555 | |
556 | if (final_sequence | |
557 | && INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) | |
558 | print_slot (final_sequence); | |
b9654711 | 559 | } |
bc45ade3 SC |
560 | return ""; |
561 | ||
8aa2a305 JW |
562 | case 16: |
563 | /* A branch with an unfilled delay slot. */ | |
564 | case 18: | |
565 | /* Branches a long way away. */ | |
566 | { | |
567 | /* The call to print_slot will clobber the operands. */ | |
568 | rtx op0 = operands[0]; | |
bc45ade3 | 569 | |
79b2746a JW |
570 | /* If the instruction in the delay slot is annulled (true), then |
571 | there is no delay slot where we can put it now. The only safe | |
572 | place for it is after the label. */ | |
573 | ||
8aa2a305 JW |
574 | if (final_sequence) |
575 | { | |
79b2746a JW |
576 | fprintf (asm_out_file, "\tb%c%s\tLF%d\n", logic ? 'f' : 't', |
577 | INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)) | |
578 | ? "" : ".s", label); | |
579 | if (! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) | |
580 | print_slot (final_sequence); | |
8aa2a305 JW |
581 | } |
582 | else | |
583 | fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label); | |
bc45ade3 | 584 | |
8aa2a305 JW |
585 | output_far_jump (insn, op0); |
586 | fprintf (asm_out_file, "LF%d:\n", label); | |
79b2746a JW |
587 | |
588 | if (final_sequence | |
589 | && INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) | |
590 | print_slot (final_sequence); | |
8aa2a305 | 591 | } |
79b2746a | 592 | return ""; |
bc45ade3 | 593 | } |
8aa2a305 | 594 | return "bad"; |
bc45ade3 | 595 | } |
8e87e161 | 596 | \f |
8aa2a305 | 597 | /* A copy of the option structure defined in toplev.c. */ |
bc45ade3 | 598 | |
0d7e008e | 599 | struct option |
bc45ade3 | 600 | { |
0d7e008e SC |
601 | char *string; |
602 | int *variable; | |
603 | int on_value; | |
604 | }; | |
b9654711 | 605 | |
8aa2a305 JW |
606 | /* Output a single output option string NAME to FILE, without generating |
607 | lines longer than MAX. */ | |
608 | ||
0d7e008e SC |
609 | static int |
610 | output_option (file, sep, type, name, indent, pos, max) | |
611 | FILE *file; | |
612 | char *sep; | |
613 | char *type; | |
614 | char *name; | |
615 | char *indent; | |
616 | int pos; | |
617 | int max; | |
618 | { | |
619 | if (strlen (sep) + strlen (type) + strlen (name) + pos > max) | |
bc45ade3 | 620 | { |
0d7e008e SC |
621 | fprintf (file, indent); |
622 | return fprintf (file, "%s%s", type, name); | |
b9654711 | 623 | } |
0d7e008e SC |
624 | return pos + fprintf (file, "%s%s%s", sep, type, name); |
625 | } | |
bc45ade3 | 626 | |
8aa2a305 JW |
627 | /* A copy of the target_switches variable in toplev.c. */ |
628 | ||
0d7e008e SC |
629 | static struct |
630 | { | |
631 | char *name; | |
632 | int value; | |
8aa2a305 | 633 | } m_options[] = TARGET_SWITCHES; |
bc45ade3 | 634 | |
8aa2a305 | 635 | /* Output all options to the assembly language file. */ |
bc45ade3 | 636 | |
0d7e008e SC |
637 | static void |
638 | output_options (file, f_options, f_len, W_options, W_len, | |
639 | pos, max, sep, indent, term) | |
640 | FILE *file; | |
641 | struct option *f_options; | |
642 | struct option *W_options; | |
643 | int f_len, W_len; | |
644 | int pos; | |
645 | int max; | |
646 | char *sep; | |
647 | char *indent; | |
648 | char *term; | |
649 | { | |
650 | register int j; | |
bc45ade3 | 651 | |
0d7e008e SC |
652 | if (optimize) |
653 | pos = output_option (file, sep, "-O", "", indent, pos, max); | |
654 | if (write_symbols != NO_DEBUG) | |
655 | pos = output_option (file, sep, "-g", "", indent, pos, max); | |
0d7e008e SC |
656 | if (profile_flag) |
657 | pos = output_option (file, sep, "-p", "", indent, pos, max); | |
658 | if (profile_block_flag) | |
659 | pos = output_option (file, sep, "-a", "", indent, pos, max); | |
bc45ade3 | 660 | |
0d7e008e SC |
661 | for (j = 0; j < f_len; j++) |
662 | if (*f_options[j].variable == f_options[j].on_value) | |
663 | pos = output_option (file, sep, "-f", f_options[j].string, | |
664 | indent, pos, max); | |
bc45ade3 | 665 | |
0d7e008e SC |
666 | for (j = 0; j < W_len; j++) |
667 | if (*W_options[j].variable == W_options[j].on_value) | |
668 | pos = output_option (file, sep, "-W", W_options[j].string, | |
669 | indent, pos, max); | |
bc45ade3 | 670 | |
0d7e008e SC |
671 | for (j = 0; j < sizeof m_options / sizeof m_options[0]; j++) |
672 | if (m_options[j].name[0] != '\0' | |
673 | && m_options[j].value > 0 | |
674 | && ((m_options[j].value & target_flags) | |
675 | == m_options[j].value)) | |
676 | pos = output_option (file, sep, "-m", m_options[j].name, | |
677 | indent, pos, max); | |
bc45ade3 | 678 | |
0d7e008e | 679 | fprintf (file, term); |
0d7e008e | 680 | } |
b9654711 | 681 | |
8aa2a305 JW |
682 | /* Output to FILE the start of the assembler file. */ |
683 | ||
0d7e008e SC |
684 | void |
685 | output_file_start (file, f_options, f_len, W_options, W_len) | |
686 | FILE *file; | |
687 | struct option *f_options; | |
688 | struct option *W_options; | |
689 | int f_len, W_len; | |
bc45ade3 | 690 | { |
0d7e008e | 691 | register int pos; |
b9654711 | 692 | |
0d7e008e | 693 | output_file_directive (file, main_input_filename); |
b9654711 | 694 | |
0d7e008e SC |
695 | /* Switch to the data section so that the coffsem symbol and the |
696 | gcc2_compiled. symbol aren't in the text section. */ | |
697 | data_section (); | |
b9654711 | 698 | |
00f8ff66 | 699 | pos = fprintf (file, "\n! Hitachi SH cc1 (%s) arguments:", version_string); |
0d7e008e SC |
700 | output_options (file, f_options, f_len, W_options, W_len, |
701 | pos, 75, " ", "\n! ", "\n\n"); | |
8aa2a305 JW |
702 | |
703 | if (TARGET_LITTLE_ENDIAN) | |
704 | fprintf (file, "\t.little\n"); | |
bc45ade3 | 705 | } |
0d7e008e | 706 | \f |
16bea517 | 707 | /* Actual number of instructions used to make a shift by N. */ |
8aa2a305 | 708 | static char ashiftrt_insns[] = |
16bea517 JW |
709 | { 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}; |
710 | ||
711 | /* Left shift and logical right shift are the same. */ | |
8aa2a305 | 712 | static char shift_insns[] = |
16bea517 | 713 | { 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 | 714 | |
16bea517 JW |
715 | /* Individual shift amounts needed to get the above length sequences. |
716 | One bit right shifts clobber the T bit, so when possible, put one bit | |
717 | shifts in the middle of the sequence, so the ends are eligible for | |
718 | branch delay slots. */ | |
8aa2a305 | 719 | static short shift_amounts[32][5] = { |
16bea517 JW |
720 | {0}, {1}, {2}, {2, 1}, |
721 | {2, 2}, {2, 1, 2}, {2, 2, 2}, {2, 2, 1, 2}, | |
722 | {8}, {8, 1}, {8, 2}, {8, 1, 2}, | |
723 | {8, 2, 2}, {8, 2, 1, 2}, {8, -2, 8}, {8, -1, 8}, | |
724 | {16}, {16, 1}, {16, 2}, {16, 1, 2}, | |
725 | {16, 2, 2}, {16, 2, 1, 2}, {16, -2, 8}, {16, -1, 8}, | |
726 | {16, 8}, {16, 1, 8}, {16, 8, 2}, {16, 8, 1, 2}, | |
1d3534c0 | 727 | {16, 8, 2, 2}, {16, -1, -2, 16}, {16, -2, 16}, {16, -1, 16}}; |
16bea517 JW |
728 | |
729 | /* This is used in length attributes in sh.md to help compute the length | |
730 | of arbitrary constant shift instructions. */ | |
bc45ade3 | 731 | |
16bea517 JW |
732 | int |
733 | shift_insns_rtx (insn) | |
734 | rtx insn; | |
735 | { | |
736 | rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); | |
737 | int shift_count = INTVAL (XEXP (set_src, 1)); | |
738 | enum rtx_code shift_code = GET_CODE (set_src); | |
00f8ff66 | 739 | |
16bea517 JW |
740 | switch (shift_code) |
741 | { | |
742 | case ASHIFTRT: | |
743 | return ashiftrt_insns[shift_count]; | |
744 | case LSHIFTRT: | |
745 | case ASHIFT: | |
746 | return shift_insns[shift_count]; | |
747 | default: | |
748 | abort(); | |
749 | } | |
750 | } | |
751 | ||
16bea517 | 752 | /* Return the cost of a shift. */ |
bc45ade3 | 753 | |
0d7e008e | 754 | int |
8aa2a305 JW |
755 | shiftcosts (x) |
756 | rtx x; | |
bc45ade3 | 757 | { |
8aa2a305 JW |
758 | int value = INTVAL (XEXP (x, 1)); |
759 | ||
16bea517 | 760 | /* If shift by a non constant, then this will be expensive. */ |
8aa2a305 | 761 | if (GET_CODE (XEXP (x, 1)) != CONST_INT) |
00f8ff66 | 762 | { |
20b04867 JW |
763 | if (TARGET_SH3) |
764 | return 2; | |
765 | /* If not an sh3 then we don't even have an instruction for it. */ | |
00f8ff66 SC |
766 | return 20; |
767 | } | |
bc45ade3 | 768 | |
16bea517 | 769 | /* Otherwise, return the true cost in instructions. */ |
8aa2a305 JW |
770 | if (GET_CODE (x) == ASHIFTRT) |
771 | return ashiftrt_insns[value]; | |
772 | else | |
773 | return shift_insns[value]; | |
0d7e008e | 774 | } |
b9654711 | 775 | |
8aa2a305 JW |
776 | /* Return the cost of an AND operation. */ |
777 | ||
8e87e161 | 778 | int |
8aa2a305 JW |
779 | andcosts (x) |
780 | rtx x; | |
0d7e008e SC |
781 | { |
782 | int i; | |
8aa2a305 | 783 | |
a6f71af5 | 784 | /* Anding with a register is a single cycle and instruction. */ |
8aa2a305 | 785 | if (GET_CODE (XEXP (x, 1)) != CONST_INT) |
a6f71af5 | 786 | return 1; |
8aa2a305 JW |
787 | |
788 | i = INTVAL (XEXP (x, 1)); | |
a6f71af5 | 789 | /* These constants are single cycle extu.[bw] instructions. */ |
0d7e008e | 790 | if (i == 0xff || i == 0xffff) |
a6f71af5 JW |
791 | return 1; |
792 | /* Constants that can be used in an and immediate instruction is a single | |
793 | cycle, but this requires r0, so make it a little more expensive. */ | |
794 | if (CONST_OK_FOR_L (i)) | |
0d7e008e | 795 | return 2; |
a6f71af5 JW |
796 | /* Constants that can be loaded with a mov immediate and an and. |
797 | This case is probably unnecessary. */ | |
0d7e008e | 798 | if (CONST_OK_FOR_I (i)) |
a6f71af5 JW |
799 | return 2; |
800 | /* Any other constants requires a 2 cycle pc-relative load plus an and. | |
801 | This case is probably unnecessary. */ | |
802 | return 3; | |
0d7e008e | 803 | } |
d3ae8277 | 804 | |
16bea517 | 805 | /* Return the cost of a multiply. */ |
0d7e008e | 806 | int |
8aa2a305 JW |
807 | multcosts (x) |
808 | rtx x; | |
0d7e008e SC |
809 | { |
810 | if (TARGET_SH2) | |
d3ae8277 SC |
811 | { |
812 | /* We have a mul insn, so we can never take more than the mul and the | |
a7771f78 | 813 | read of the mac reg, but count more because of the latency and extra |
16bea517 | 814 | reg usage. */ |
d3ae8277 | 815 | if (TARGET_SMALLCODE) |
8e87e161 | 816 | return 2; |
a7771f78 | 817 | return 3; |
d3ae8277 SC |
818 | } |
819 | ||
a7771f78 | 820 | /* If we're aiming at small code, then just count the number of |
16bea517 | 821 | insns in a multiply call sequence. */ |
8e87e161 | 822 | if (TARGET_SMALLCODE) |
8aa2a305 | 823 | return 5; |
d3ae8277 | 824 | |
16bea517 | 825 | /* Otherwise count all the insns in the routine we'd be calling too. */ |
d3ae8277 | 826 | return 20; |
0d7e008e | 827 | } |
b9654711 | 828 | |
16bea517 | 829 | /* Code to expand a shift. */ |
b9654711 | 830 | |
0d7e008e SC |
831 | void |
832 | gen_ashift (type, n, reg) | |
833 | int type; | |
834 | int n; | |
835 | rtx reg; | |
836 | { | |
16bea517 JW |
837 | /* Negative values here come from the shift_amounts array. */ |
838 | if (n < 0) | |
839 | { | |
840 | if (type == ASHIFT) | |
841 | type = LSHIFTRT; | |
842 | else | |
843 | type = ASHIFT; | |
844 | n = -n; | |
845 | } | |
846 | ||
0d7e008e | 847 | switch (type) |
bc45ade3 | 848 | { |
0d7e008e SC |
849 | case ASHIFTRT: |
850 | emit_insn (gen_ashrsi3_k (reg, reg, GEN_INT (n))); | |
851 | break; | |
852 | case LSHIFTRT: | |
16bea517 JW |
853 | if (n == 1) |
854 | emit_insn (gen_lshrsi3_m (reg, reg, GEN_INT (n))); | |
855 | else | |
856 | emit_insn (gen_lshrsi3_k (reg, reg, GEN_INT (n))); | |
0d7e008e SC |
857 | break; |
858 | case ASHIFT: | |
5325c0fa | 859 | emit_insn (gen_ashlsi3_k (reg, reg, GEN_INT (n))); |
0d7e008e | 860 | break; |
bc45ade3 | 861 | } |
bc45ade3 | 862 | } |
bc45ade3 | 863 | |
8aa2a305 JW |
864 | /* Output RTL to split a constant shift into its component SH constant |
865 | shift instructions. */ | |
866 | ||
20b04867 JW |
867 | /* ??? For SH3, should reject constant shifts when slower than loading the |
868 | shift count into a register? */ | |
8aa2a305 | 869 | |
0d7e008e SC |
870 | int |
871 | gen_shifty_op (code, operands) | |
872 | int code; | |
873 | rtx *operands; | |
bc45ade3 | 874 | { |
16bea517 | 875 | int value = INTVAL (operands[2]); |
8aa2a305 | 876 | int max, i; |
00f8ff66 | 877 | |
8aa2a305 | 878 | if (value == 31) |
16bea517 | 879 | { |
8aa2a305 | 880 | if (code == LSHIFTRT) |
0d7e008e | 881 | { |
8aa2a305 JW |
882 | emit_insn (gen_rotlsi3_1 (operands[0], operands[0])); |
883 | emit_insn (gen_movt (operands[0])); | |
884 | return; | |
16bea517 | 885 | } |
8aa2a305 | 886 | else if (code == ASHIFT) |
16bea517 | 887 | { |
8aa2a305 JW |
888 | /* There is a two instruction sequence for 31 bit left shifts, |
889 | but it requires r0. */ | |
890 | if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 0) | |
0d7e008e | 891 | { |
8aa2a305 JW |
892 | emit_insn (gen_andsi3 (operands[0], operands[0], const1_rtx)); |
893 | emit_insn (gen_rotlsi3_31 (operands[0], operands[0])); | |
894 | return; | |
0d7e008e | 895 | } |
16bea517 | 896 | } |
8aa2a305 | 897 | } |
a9f71ad8 | 898 | |
8aa2a305 JW |
899 | max = shift_insns[value]; |
900 | for (i = 0; i < max; i++) | |
901 | gen_ashift (code, shift_amounts[value][i], operands[0]); | |
902 | } | |
903 | ||
904 | /* Output RTL for an arithmetic right shift. */ | |
905 | ||
906 | /* ??? Rewrite to use super-optimizer sequences. */ | |
907 | ||
908 | int | |
909 | expand_ashiftrt (operands) | |
910 | rtx *operands; | |
911 | { | |
912 | rtx wrk; | |
913 | char func[18]; | |
914 | tree func_name; | |
915 | int value; | |
916 | ||
20b04867 JW |
917 | if (TARGET_SH3 && GET_CODE (operands[2]) != CONST_INT) |
918 | { | |
919 | rtx count = copy_to_mode_reg (SImode, operands[2]); | |
920 | emit_insn (gen_negsi2 (count, count)); | |
921 | emit_insn (gen_ashrsi3_d (operands[0], operands[1], count)); | |
922 | return 1; | |
923 | } | |
8aa2a305 JW |
924 | if (GET_CODE (operands[2]) != CONST_INT) |
925 | return 0; | |
926 | ||
927 | value = INTVAL (operands[2]); | |
928 | ||
929 | if (value == 31) | |
930 | { | |
931 | emit_insn (gen_ashrsi2_31 (operands[0], operands[1])); | |
932 | return 1; | |
933 | } | |
934 | else if (value >= 16 && value <= 19) | |
935 | { | |
936 | wrk = gen_reg_rtx (SImode); | |
937 | emit_insn (gen_ashrsi2_16 (wrk, operands[1])); | |
938 | value -= 16; | |
939 | while (value--) | |
940 | gen_ashift (ASHIFTRT, 1, wrk); | |
941 | emit_move_insn (operands[0], wrk); | |
942 | return 1; | |
a9f71ad8 | 943 | } |
8aa2a305 JW |
944 | /* Expand a short sequence inline, longer call a magic routine. */ |
945 | else if (value <= 5) | |
946 | { | |
947 | wrk = gen_reg_rtx (SImode); | |
948 | emit_move_insn (wrk, operands[1]); | |
949 | while (value--) | |
950 | gen_ashift (ASHIFTRT, 1, wrk); | |
951 | emit_move_insn (operands[0], wrk); | |
952 | return 1; | |
953 | } | |
954 | ||
955 | wrk = gen_reg_rtx (Pmode); | |
956 | ||
957 | /* Load the value into an arg reg and call a helper. */ | |
958 | emit_move_insn (gen_rtx (REG, SImode, 4), operands[1]); | |
959 | sprintf (func, "__ashiftrt_r4_%d", value); | |
960 | func_name = get_identifier (func); | |
961 | emit_move_insn (wrk, gen_rtx (SYMBOL_REF, Pmode, | |
962 | IDENTIFIER_POINTER (func_name))); | |
963 | emit_insn (gen_ashrsi3_n (GEN_INT (value), wrk)); | |
964 | emit_move_insn (operands[0], gen_rtx (REG, SImode, 4)); | |
965 | return 1; | |
bc45ade3 | 966 | } |
8aa2a305 JW |
967 | \f |
968 | /* The SH cannot load a large constant into a register, constants have to | |
969 | come from a pc relative load. The reference of a pc relative load | |
970 | instruction must be less than 1k infront of the instruction. This | |
971 | means that we often have to dump a constant inside a function, and | |
972 | generate code to branch around it. | |
bc45ade3 | 973 | |
8aa2a305 JW |
974 | It is important to minimize this, since the branches will slow things |
975 | down and make things bigger. | |
976 | ||
977 | Worst case code looks like: | |
978 | ||
979 | mov.l L1,rn | |
980 | bra L2 | |
981 | nop | |
982 | align | |
983 | L1: .long value | |
984 | L2: | |
985 | .. | |
986 | ||
987 | mov.l L3,rn | |
988 | bra L4 | |
989 | nop | |
990 | align | |
991 | L3: .long value | |
992 | L4: | |
993 | .. | |
994 | ||
995 | We fix this by performing a scan before scheduling, which notices which | |
996 | instructions need to have their operands fetched from the constant table | |
997 | and builds the table. | |
998 | ||
999 | The algorithm is: | |
1000 | ||
1001 | scan, find an instruction which needs a pcrel move. Look forward, find the | |
1002 | last barrier which is within MAX_COUNT bytes of the requirement. | |
1003 | If there isn't one, make one. Process all the instructions between | |
1004 | the find and the barrier. | |
1005 | ||
1006 | In the above example, we can tell that L3 is within 1k of L1, so | |
1007 | the first move can be shrunk from the 3 insn+constant sequence into | |
1008 | just 1 insn, and the constant moved to L3 to make: | |
1009 | ||
1010 | mov.l L1,rn | |
1011 | .. | |
1012 | mov.l L3,rn | |
1013 | bra L4 | |
1014 | nop | |
1015 | align | |
1016 | L3:.long value | |
1017 | L4:.long value | |
1018 | ||
1019 | Then the second move becomes the target for the shortening process. */ | |
1020 | ||
1021 | typedef struct | |
1022 | { | |
1023 | rtx value; /* Value in table. */ | |
1024 | rtx label; /* Label of value. */ | |
1025 | enum machine_mode mode; /* Mode of value. */ | |
1026 | } pool_node; | |
1027 | ||
1028 | /* The maximum number of constants that can fit into one pool, since | |
1029 | the pc relative range is 0...1020 bytes and constants are at least 4 | |
1030 | bytes long. */ | |
1031 | ||
1032 | #define MAX_POOL_SIZE (1020/4) | |
1033 | static pool_node pool_vector[MAX_POOL_SIZE]; | |
1034 | static int pool_size; | |
1035 | ||
1036 | /* ??? If we need a constant in HImode which is the truncated value of a | |
1037 | constant we need in SImode, we could combine the two entries thus saving | |
1038 | two bytes. Is this common enough to be worth the effort of implementing | |
1039 | it? */ | |
1040 | ||
1041 | /* ??? This stuff should be done at the same time that we shorten branches. | |
1042 | As it is now, we must assume that all branches are the maximum size, and | |
1043 | this causes us to almost always output constant pools sooner than | |
1044 | necessary. */ | |
1045 | ||
1046 | /* Add a constant to the pool and return its label. */ | |
1047 | ||
1048 | static rtx | |
1049 | add_constant (x, mode) | |
1050 | rtx x; | |
1051 | enum machine_mode mode; | |
0d7e008e SC |
1052 | { |
1053 | int i; | |
8aa2a305 JW |
1054 | rtx lab; |
1055 | ||
1056 | /* First see if we've already got it. */ | |
1057 | for (i = 0; i < pool_size; i++) | |
0d7e008e | 1058 | { |
8aa2a305 JW |
1059 | if (x->code == pool_vector[i].value->code |
1060 | && mode == pool_vector[i].mode) | |
0d7e008e | 1061 | { |
8aa2a305 JW |
1062 | if (x->code == CODE_LABEL) |
1063 | { | |
1064 | if (XINT (x, 3) != XINT (pool_vector[i].value, 3)) | |
1065 | continue; | |
1066 | } | |
1067 | if (rtx_equal_p (x, pool_vector[i].value)) | |
1068 | return pool_vector[i].label; | |
0d7e008e | 1069 | } |
0d7e008e | 1070 | } |
b9654711 | 1071 | |
8aa2a305 JW |
1072 | /* Need a new one. */ |
1073 | pool_vector[pool_size].value = x; | |
1074 | lab = gen_label_rtx (); | |
1075 | pool_vector[pool_size].mode = mode; | |
1076 | pool_vector[pool_size].label = lab; | |
1077 | pool_size++; | |
1078 | return lab; | |
0d7e008e | 1079 | } |
16bea517 JW |
1080 | |
1081 | /* Output the literal table. */ | |
b9654711 | 1082 | |
b9654711 | 1083 | static void |
0d7e008e SC |
1084 | dump_table (scan) |
1085 | rtx scan; | |
b9654711 | 1086 | { |
0d7e008e | 1087 | int i; |
0d7e008e | 1088 | int need_align = 1; |
b9654711 | 1089 | |
16bea517 | 1090 | /* Do two passes, first time dump out the HI sized constants. */ |
b9654711 | 1091 | |
0d7e008e | 1092 | for (i = 0; i < pool_size; i++) |
b9654711 | 1093 | { |
8aa2a305 JW |
1094 | pool_node *p = &pool_vector[i]; |
1095 | ||
0d7e008e SC |
1096 | if (p->mode == HImode) |
1097 | { | |
1098 | if (need_align) | |
1099 | { | |
1100 | scan = emit_insn_after (gen_align_2 (), scan); | |
1101 | need_align = 0; | |
1102 | } | |
1103 | scan = emit_label_after (p->label, scan); | |
1104 | scan = emit_insn_after (gen_consttable_2 (p->value), scan); | |
1105 | } | |
b9654711 | 1106 | } |
8aa2a305 | 1107 | |
0d7e008e | 1108 | need_align = 1; |
b9654711 | 1109 | |
0d7e008e | 1110 | for (i = 0; i < pool_size; i++) |
b9654711 | 1111 | { |
8aa2a305 | 1112 | pool_node *p = &pool_vector[i]; |
b9654711 | 1113 | |
0d7e008e | 1114 | switch (p->mode) |
b9654711 | 1115 | { |
0d7e008e SC |
1116 | case HImode: |
1117 | break; | |
1118 | case SImode: | |
1119 | if (need_align) | |
b9654711 | 1120 | { |
0d7e008e | 1121 | need_align = 0; |
d3ae8277 | 1122 | scan = emit_label_after (gen_label_rtx (), scan); |
0d7e008e | 1123 | scan = emit_insn_after (gen_align_4 (), scan); |
b9654711 | 1124 | } |
0d7e008e SC |
1125 | scan = emit_label_after (p->label, scan); |
1126 | scan = emit_insn_after (gen_consttable_4 (p->value), scan); | |
1127 | break; | |
1128 | case DImode: | |
1129 | if (need_align) | |
1130 | { | |
1131 | need_align = 0; | |
d3ae8277 | 1132 | scan = emit_label_after (gen_label_rtx (), scan); |
0d7e008e SC |
1133 | scan = emit_insn_after (gen_align_4 (), scan); |
1134 | } | |
1135 | scan = emit_label_after (p->label, scan); | |
1136 | scan = emit_insn_after (gen_consttable_8 (p->value), scan); | |
1137 | break; | |
1138 | default: | |
1139 | abort (); | |
1140 | break; | |
b9654711 SC |
1141 | } |
1142 | } | |
b9654711 | 1143 | |
0d7e008e SC |
1144 | scan = emit_insn_after (gen_consttable_end (), scan); |
1145 | scan = emit_barrier_after (scan); | |
1146 | pool_size = 0; | |
1147 | } | |
b9654711 | 1148 | |
8aa2a305 JW |
1149 | /* Return non-zero if constant would be an ok source for a |
1150 | mov.w instead of a mov.l. */ | |
b9654711 | 1151 | |
16bea517 | 1152 | static int |
8aa2a305 | 1153 | hi_const (src) |
0d7e008e | 1154 | rtx src; |
0d7e008e | 1155 | { |
8aa2a305 JW |
1156 | return (GET_CODE (src) == CONST_INT |
1157 | && INTVAL (src) >= -32768 | |
1158 | && INTVAL (src) <= 32767); | |
b9654711 SC |
1159 | } |
1160 | ||
8aa2a305 JW |
1161 | /* Non-zero if the insn is a move instruction which needs to be fixed. */ |
1162 | ||
1163 | /* ??? For a DImode/DFmode moves, we don't need to fix it if each half of the | |
1164 | CONST_DOUBLE input value is CONST_OK_FOR_I. For a SFmode move, we don't | |
1165 | need to fix it if the input value is CONST_OK_FOR_I. */ | |
1166 | ||
1167 | static int | |
1168 | broken_move (insn) | |
1169 | rtx insn; | |
b9654711 | 1170 | { |
8aa2a305 JW |
1171 | if (GET_CODE (insn) == INSN |
1172 | && GET_CODE (PATTERN (insn)) == SET | |
1173 | /* We can load any 8 bit value if we don't care what the high | |
1174 | order bits end up as. */ | |
1175 | && GET_MODE (SET_DEST (PATTERN (insn))) != QImode | |
1176 | && CONSTANT_P (SET_SRC (PATTERN (insn))) | |
1177 | && (GET_CODE (SET_SRC (PATTERN (insn))) != CONST_INT | |
1178 | || ! CONST_OK_FOR_I (INTVAL (SET_SRC (PATTERN (insn)))))) | |
d3ae8277 SC |
1179 | return 1; |
1180 | ||
8aa2a305 | 1181 | return 0; |
b9654711 | 1182 | } |
b9654711 | 1183 | |
8aa2a305 JW |
1184 | /* Find the last barrier from insn FROM which is close enough to hold the |
1185 | constant pool. If we can't find one, then create one near the end of | |
1186 | the range. */ | |
b9654711 | 1187 | |
5325c0fa JW |
1188 | /* ??? It would be good to put constant pool tables between a case jump and |
1189 | the jump table. This fails for two reasons. First, there is no | |
1190 | barrier after the case jump. This is a bug in the casesi pattern. | |
1191 | Second, inserting the table here may break the mova instruction that | |
1192 | loads the jump table address, by moving the jump table too far away. | |
1193 | We fix that problem by never outputting the constant pool between a mova | |
1194 | and its label. */ | |
1195 | ||
8aa2a305 | 1196 | static rtx |
06c386ea SC |
1197 | find_barrier (from) |
1198 | rtx from; | |
b9654711 | 1199 | { |
0d7e008e SC |
1200 | int count_si = 0; |
1201 | int count_hi = 0; | |
1202 | int found_hi = 0; | |
1203 | int found_si = 0; | |
1204 | rtx found_barrier = 0; | |
5325c0fa | 1205 | rtx found_mova = 0; |
8aa2a305 JW |
1206 | |
1207 | /* For HImode: range is 510, add 4 because pc counts from address of | |
1208 | second instruction after this one, subtract 2 for the jump instruction | |
1209 | that we may need to emit before the table. This gives 512. | |
1210 | For SImode: range is 1020, add 4 because pc counts from address of | |
1211 | second instruction after this one, subtract 2 in case pc is 2 byte | |
1212 | aligned, subtract 2 for the jump instruction that we may need to emit | |
1213 | before the table. This gives 1020. */ | |
1214 | while (from && count_si < 1020 && count_hi < 512) | |
0d7e008e | 1215 | { |
5dbcc9c0 | 1216 | int inc = get_attr_length (from); |
8aa2a305 | 1217 | |
0d7e008e | 1218 | if (GET_CODE (from) == BARRIER) |
8aa2a305 JW |
1219 | found_barrier = from; |
1220 | ||
8aa2a305 | 1221 | if (broken_move (from)) |
0d7e008e SC |
1222 | { |
1223 | rtx src = SET_SRC (PATTERN (from)); | |
8aa2a305 | 1224 | |
0d7e008e | 1225 | if (hi_const (src)) |
00e94d65 RK |
1226 | { |
1227 | found_hi = 1; | |
1228 | /* We put the short constants before the long constants, so | |
1229 | we must count the length of short constants in the range | |
1230 | for the long constants. */ | |
1231 | /* ??? This isn't optimal, but is easy to do. */ | |
1232 | if (found_si) | |
1233 | count_si += 2; | |
1234 | } | |
0d7e008e SC |
1235 | else |
1236 | found_si = 1; | |
0d7e008e | 1237 | } |
5325c0fa | 1238 | |
5325c0fa JW |
1239 | if (GET_CODE (from) == INSN |
1240 | && GET_CODE (PATTERN (from)) == SET | |
16bea517 JW |
1241 | && GET_CODE (SET_SRC (PATTERN (from))) == UNSPEC |
1242 | && XINT (SET_SRC (PATTERN (from)), 1) == 1) | |
5325c0fa JW |
1243 | found_mova = from; |
1244 | else if (GET_CODE (from) == JUMP_INSN | |
1245 | && (GET_CODE (PATTERN (from)) == ADDR_VEC | |
1246 | || GET_CODE (PATTERN (from)) == ADDR_DIFF_VEC)) | |
1247 | found_mova = 0; | |
1248 | ||
0d7e008e SC |
1249 | if (found_si) |
1250 | count_si += inc; | |
1251 | if (found_hi) | |
1252 | count_hi += inc; | |
1253 | from = NEXT_INSN (from); | |
1254 | } | |
1255 | ||
5325c0fa JW |
1256 | /* Insert the constant pool table before the mova instruction, to prevent |
1257 | the mova label reference from going out of range. */ | |
1258 | if (found_mova) | |
1259 | from = found_mova; | |
1260 | ||
8aa2a305 | 1261 | if (! found_barrier) |
b9654711 | 1262 | { |
8aa2a305 JW |
1263 | /* We didn't find a barrier in time to dump our stuff, |
1264 | so we'll make one. */ | |
0d7e008e | 1265 | rtx label = gen_label_rtx (); |
8aa2a305 | 1266 | |
5dbcc9c0 RK |
1267 | /* If we exceeded the range, then we must back up over the last |
1268 | instruction we looked at. Otherwise, we just need to undo the | |
1269 | NEXT_INSN at the end of the loop. */ | |
1270 | if (count_hi > 512 || count_si > 1020) | |
1271 | from = PREV_INSN (PREV_INSN (from)); | |
1272 | else | |
1273 | from = PREV_INSN (from); | |
1274 | ||
8aa2a305 JW |
1275 | /* Walk back to be just before any jump or label. |
1276 | Putting it before a label reduces the number of times the branch | |
1277 | around the constant pool table will be hit. Putting it before | |
1278 | a jump makes it more likely that the bra delay slot will be | |
1279 | filled. */ | |
1280 | while (GET_CODE (from) == JUMP_INSN || GET_CODE (from) == NOTE | |
8e87e161 | 1281 | || GET_CODE (from) == CODE_LABEL) |
8aa2a305 JW |
1282 | from = PREV_INSN (from); |
1283 | ||
0d7e008e SC |
1284 | from = emit_jump_insn_after (gen_jump (label), from); |
1285 | JUMP_LABEL (from) = label; | |
e081ed26 | 1286 | LABEL_NUSES (label) = 1; |
0d7e008e SC |
1287 | found_barrier = emit_barrier_after (from); |
1288 | emit_label_after (label, found_barrier); | |
b9654711 | 1289 | } |
b9654711 | 1290 | |
8aa2a305 | 1291 | return found_barrier; |
0d7e008e | 1292 | } |
b9654711 | 1293 | |
8aa2a305 | 1294 | /* Exported to toplev.c. |
b9654711 | 1295 | |
0d7e008e | 1296 | Scan the function looking for move instructions which have to be changed to |
8aa2a305 | 1297 | pc-relative loads and insert the literal tables. */ |
b9654711 | 1298 | |
0d7e008e SC |
1299 | void |
1300 | machine_dependent_reorg (first) | |
1301 | rtx first; | |
1302 | { | |
1303 | rtx insn; | |
8aa2a305 | 1304 | |
0d7e008e SC |
1305 | for (insn = first; insn; insn = NEXT_INSN (insn)) |
1306 | { | |
1307 | if (broken_move (insn)) | |
1308 | { | |
0d7e008e | 1309 | rtx scan; |
8aa2a305 JW |
1310 | /* Scan ahead looking for a barrier to stick the constant table |
1311 | behind. */ | |
0d7e008e | 1312 | rtx barrier = find_barrier (insn); |
b9654711 | 1313 | |
16bea517 | 1314 | /* Now find all the moves between the points and modify them. */ |
0d7e008e SC |
1315 | for (scan = insn; scan != barrier; scan = NEXT_INSN (scan)) |
1316 | { | |
1317 | if (broken_move (scan)) | |
1318 | { | |
1319 | rtx pat = PATTERN (scan); | |
1320 | rtx src = SET_SRC (pat); | |
1321 | rtx dst = SET_DEST (pat); | |
1322 | enum machine_mode mode = GET_MODE (dst); | |
1323 | rtx lab; | |
1324 | rtx newinsn; | |
1325 | rtx newsrc; | |
0d7e008e SC |
1326 | |
1327 | if (mode == SImode && hi_const (src)) | |
1328 | { | |
23ed92ca | 1329 | int offset = 0; |
8aa2a305 | 1330 | |
0d7e008e | 1331 | mode = HImode; |
d3ae8277 | 1332 | while (GET_CODE (dst) == SUBREG) |
23ed92ca JW |
1333 | { |
1334 | offset += SUBREG_WORD (dst); | |
1335 | dst = SUBREG_REG (dst); | |
1336 | } | |
1337 | dst = gen_rtx (REG, HImode, REGNO (dst) + offset); | |
0d7e008e | 1338 | } |
8aa2a305 | 1339 | |
0d7e008e SC |
1340 | lab = add_constant (src, mode); |
1341 | newsrc = gen_rtx (MEM, mode, | |
1342 | gen_rtx (LABEL_REF, VOIDmode, lab)); | |
8aa2a305 JW |
1343 | RTX_UNCHANGING_P (newsrc) = 1; |
1344 | newinsn = emit_insn_after (gen_rtx (SET, VOIDmode, | |
1345 | dst, newsrc), scan); | |
0d7e008e | 1346 | |
0d7e008e SC |
1347 | delete_insn (scan); |
1348 | scan = newinsn; | |
1349 | } | |
1350 | } | |
1351 | dump_table (barrier); | |
1352 | } | |
1353 | } | |
b9654711 SC |
1354 | } |
1355 | ||
8aa2a305 JW |
1356 | /* Dump out instruction addresses, which is useful for debugging the |
1357 | constant pool table stuff. */ | |
1358 | ||
1359 | /* ??? This is unnecessary, and probably should be deleted. This makes | |
1360 | the insn_addresses declaration above unnecessary. */ | |
1361 | ||
1362 | /* ??? The addresses printed by this routine for insns are nonsense for | |
1363 | insns which are inside of a sequence where none of the inner insns have | |
1364 | variable length. This is because the second pass of shorten_branches | |
1365 | does not bother to update them. */ | |
0d7e008e | 1366 | |
8e87e161 | 1367 | void |
8aa2a305 JW |
1368 | final_prescan_insn (insn, opvec, noperands) |
1369 | rtx insn; | |
1370 | rtx *opvec; | |
1371 | int noperands; | |
b9654711 | 1372 | { |
8aa2a305 JW |
1373 | if (TARGET_DUMPISIZE) |
1374 | fprintf (asm_out_file, "\n! at %04x\n", insn_addresses[INSN_UID (insn)]); | |
0d7e008e | 1375 | } |
b9654711 | 1376 | |
8aa2a305 JW |
1377 | /* Dump out any constants accumulated in the final pass. These will |
1378 | will only be labels. */ | |
b9654711 | 1379 | |
8aa2a305 JW |
1380 | char * |
1381 | output_jump_label_table () | |
0d7e008e | 1382 | { |
8aa2a305 JW |
1383 | int i; |
1384 | ||
1385 | if (pool_size) | |
1386 | { | |
1387 | fprintf (asm_out_file, "\t.align 2\n"); | |
1388 | for (i = 0; i < pool_size; i++) | |
1389 | { | |
1390 | pool_node *p = &pool_vector[i]; | |
1391 | ||
1392 | ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", | |
1393 | CODE_LABEL_NUMBER (p->label)); | |
1394 | output_asm_insn (".long %O0", &p->value); | |
1395 | } | |
1396 | pool_size = 0; | |
1397 | } | |
b9654711 | 1398 | |
8aa2a305 JW |
1399 | return ""; |
1400 | } | |
1401 | \f | |
1402 | /* A full frame looks like: | |
16bea517 JW |
1403 | |
1404 | arg-5 | |
1405 | arg-4 | |
1406 | [ if current_function_anonymous_args | |
1407 | arg-3 | |
1408 | arg-2 | |
1409 | arg-1 | |
1410 | arg-0 ] | |
1411 | saved-fp | |
1412 | saved-r10 | |
1413 | saved-r11 | |
1414 | saved-r12 | |
1415 | saved-pr | |
1416 | local-n | |
1417 | .. | |
1418 | local-1 | |
1419 | local-0 <- fp points here. */ | |
8e87e161 | 1420 | |
8aa2a305 JW |
1421 | /* Number of bytes pushed for anonymous args, used to pass information |
1422 | between expand_prologue and expand_epilogue. */ | |
1423 | ||
1424 | static int extra_push; | |
1425 | ||
1426 | /* Adjust the stack and return the number of bytes taken to do it. */ | |
1427 | ||
1428 | static void | |
46d81ffa | 1429 | output_stack_adjust (size, reg) |
8aa2a305 | 1430 | int size; |
46d81ffa | 1431 | rtx reg; |
8aa2a305 JW |
1432 | { |
1433 | if (size) | |
1434 | { | |
1435 | rtx val = GEN_INT (size); | |
1436 | rtx insn; | |
1437 | ||
1438 | if (! CONST_OK_FOR_I (size)) | |
1439 | { | |
1440 | rtx reg = gen_rtx (REG, SImode, 3); | |
1441 | emit_insn (gen_movsi (reg, val)); | |
1442 | val = reg; | |
1443 | } | |
1444 | ||
46d81ffa | 1445 | insn = gen_addsi3 (reg, reg, val); |
8aa2a305 JW |
1446 | emit_insn (insn); |
1447 | } | |
1448 | } | |
1449 | ||
1450 | /* Output RTL to push register RN onto the stack. */ | |
1451 | ||
1452 | static void | |
1453 | push (rn) | |
1454 | int rn; | |
1455 | { | |
1456 | rtx x; | |
1457 | x = emit_insn (gen_push (gen_rtx (REG, SImode, rn))); | |
1458 | REG_NOTES (x) = gen_rtx (EXPR_LIST, REG_INC, | |
1459 | gen_rtx(REG, SImode, STACK_POINTER_REGNUM), 0); | |
1460 | } | |
1461 | ||
1462 | /* Output RTL to pop register RN from the stack. */ | |
1463 | ||
1464 | static void | |
1465 | pop (rn) | |
1466 | int rn; | |
1467 | { | |
1468 | rtx x; | |
1469 | x = emit_insn (gen_pop (gen_rtx (REG, SImode, rn))); | |
1470 | REG_NOTES (x) = gen_rtx (EXPR_LIST, REG_INC, | |
1471 | gen_rtx(REG, SImode, STACK_POINTER_REGNUM), 0); | |
1472 | } | |
1473 | ||
1474 | /* Generate code to push the regs specified in the mask, and return | |
1475 | the number of bytes the insns take. */ | |
1476 | ||
1477 | static void | |
1478 | push_regs (mask) | |
1479 | int mask; | |
1480 | { | |
1481 | int i; | |
1482 | ||
1483 | for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | |
1484 | if (mask & (1 << i)) | |
1485 | push (i); | |
1486 | } | |
1487 | ||
1488 | /* Work out the registers which need to be saved, both as a mask and a | |
1489 | count. | |
1490 | ||
1491 | If doing a pragma interrupt function, then push all regs used by the | |
1492 | function, and if we call another function (we can tell by looking at PR), | |
1493 | make sure that all the regs it clobbers are safe too. */ | |
1494 | ||
1495 | static int | |
1496 | calc_live_regs (count_ptr) | |
1497 | int *count_ptr; | |
1498 | { | |
1499 | int reg; | |
1500 | int live_regs_mask = 0; | |
1501 | int count = 0; | |
1502 | ||
1503 | for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++) | |
1504 | { | |
1505 | if (pragma_interrupt && ! pragma_trapa) | |
1506 | { | |
1507 | /* Need to save all the regs ever live. */ | |
1508 | if ((regs_ever_live[reg] | |
1509 | || (call_used_regs[reg] && regs_ever_live[PR_REG])) | |
1510 | && reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM | |
1511 | && reg != T_REG && reg != GBR_REG) | |
1512 | { | |
1513 | live_regs_mask |= 1 << reg; | |
1514 | count++; | |
1515 | } | |
1516 | } | |
1517 | else | |
1518 | { | |
1519 | /* Only push those regs which are used and need to be saved. */ | |
1520 | if (regs_ever_live[reg] && ! call_used_regs[reg]) | |
1521 | { | |
1522 | live_regs_mask |= (1 << reg); | |
1523 | count++; | |
1524 | } | |
1525 | } | |
1526 | } | |
1527 | ||
1528 | *count_ptr = count; | |
1529 | return live_regs_mask; | |
1530 | } | |
1531 | ||
1532 | /* Code to generate prologue and epilogue sequences */ | |
b9654711 SC |
1533 | |
1534 | void | |
1535 | sh_expand_prologue () | |
1536 | { | |
1537 | int live_regs_mask; | |
40d2032b | 1538 | int d, i; |
b9654711 SC |
1539 | live_regs_mask = calc_live_regs (&d); |
1540 | ||
0d7e008e | 1541 | /* We have pretend args if we had an object sent partially in registers |
8aa2a305 | 1542 | and partially on the stack, e.g. a large structure. */ |
46d81ffa | 1543 | output_stack_adjust (-current_function_pretend_args_size, stack_pointer_rtx); |
b9654711 | 1544 | |
40d2032b JW |
1545 | extra_push = 0; |
1546 | ||
1547 | /* This is set by SETUP_VARARGS to indicate that this is a varargs | |
1548 | routine. Clear it here so that the next function isn't affected. */ | |
b9654711 SC |
1549 | if (current_function_anonymous_args) |
1550 | { | |
40d2032b JW |
1551 | current_function_anonymous_args = 0; |
1552 | ||
16bea517 | 1553 | /* Push arg regs as if they'd been provided by caller in stack. */ |
b9654711 SC |
1554 | for (i = 0; i < NPARM_REGS; i++) |
1555 | { | |
1556 | int rn = NPARM_REGS + FIRST_PARM_REG - i - 1; | |
79b2746a JW |
1557 | if (i > (NPARM_REGS - current_function_args_info |
1558 | - current_function_varargs)) | |
b9654711 SC |
1559 | break; |
1560 | push (rn); | |
b9654711 SC |
1561 | extra_push += 4; |
1562 | } | |
1563 | } | |
0d7e008e | 1564 | push_regs (live_regs_mask); |
46d81ffa | 1565 | output_stack_adjust (-get_frame_size (), stack_pointer_rtx); |
b9654711 SC |
1566 | |
1567 | if (frame_pointer_needed) | |
8aa2a305 | 1568 | emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx)); |
b9654711 SC |
1569 | } |
1570 | ||
1571 | void | |
1572 | sh_expand_epilogue () | |
1573 | { | |
1574 | int live_regs_mask; | |
40d2032b | 1575 | int d, i; |
b9654711 SC |
1576 | |
1577 | live_regs_mask = calc_live_regs (&d); | |
16bea517 | 1578 | |
b9654711 | 1579 | if (frame_pointer_needed) |
46d81ffa RK |
1580 | { |
1581 | /* We deliberately make the add dependent on the frame_pointer, | |
1582 | to ensure that instruction scheduling won't move the stack pointer | |
1583 | adjust before instructions reading from the frame. This can fail | |
1584 | if there is an interrupt which then writes to the stack. */ | |
1585 | output_stack_adjust (get_frame_size (), frame_pointer_rtx); | |
1586 | emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx)); | |
1587 | } | |
1588 | else | |
1589 | output_stack_adjust (get_frame_size (), stack_pointer_rtx); | |
b9654711 | 1590 | |
16bea517 | 1591 | /* Pop all the registers. */ |
0d7e008e | 1592 | |
b9654711 SC |
1593 | for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) |
1594 | { | |
1595 | int j = (FIRST_PSEUDO_REGISTER - 1) - i; | |
1596 | if (live_regs_mask & (1 << j)) | |
8aa2a305 | 1597 | pop (j); |
b9654711 | 1598 | } |
b9654711 | 1599 | |
46d81ffa RK |
1600 | output_stack_adjust (extra_push + current_function_pretend_args_size, |
1601 | stack_pointer_rtx); | |
b9654711 SC |
1602 | } |
1603 | ||
8aa2a305 JW |
1604 | /* Clear variables at function end. */ |
1605 | ||
1606 | void | |
1607 | function_epilogue (stream, size) | |
1608 | FILE *stream; | |
1609 | int size; | |
1610 | { | |
1611 | pragma_interrupt = pragma_trapa = 0; | |
1612 | } | |
1613 | ||
0d7e008e SC |
1614 | /* Define the offset between two registers, one to be eliminated, and |
1615 | the other its replacement, at the start of a routine. */ | |
1616 | ||
1617 | int | |
1618 | initial_elimination_offset (from, to) | |
8e87e161 SC |
1619 | int from; |
1620 | int to; | |
0d7e008e SC |
1621 | { |
1622 | int regs_saved; | |
0d7e008e SC |
1623 | int total_saved_regs_space; |
1624 | int total_auto_space = get_frame_size (); | |
8e87e161 SC |
1625 | |
1626 | calc_live_regs (®s_saved); | |
0d7e008e | 1627 | total_saved_regs_space = (regs_saved) * 4; |
b9654711 | 1628 | |
0d7e008e | 1629 | if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) |
8aa2a305 JW |
1630 | return total_saved_regs_space + total_auto_space; |
1631 | ||
0d7e008e | 1632 | if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) |
8aa2a305 JW |
1633 | return total_saved_regs_space + total_auto_space; |
1634 | ||
1635 | /* Initial gap between fp and sp is 0. */ | |
0d7e008e | 1636 | if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) |
8aa2a305 JW |
1637 | return 0; |
1638 | ||
0d7e008e SC |
1639 | abort (); |
1640 | } | |
8aa2a305 | 1641 | \f |
0d7e008e | 1642 | /* Handle machine specific pragmas to be semi-compatible with Hitachi |
16bea517 | 1643 | compiler. */ |
b9654711 SC |
1644 | |
1645 | int | |
0d7e008e SC |
1646 | handle_pragma (file) |
1647 | FILE *file; | |
b9654711 | 1648 | { |
0d7e008e SC |
1649 | int c; |
1650 | char pbuf[200]; | |
1651 | int psize = 0; | |
b9654711 | 1652 | |
0d7e008e SC |
1653 | c = getc (file); |
1654 | while (c == ' ' || c == '\t') | |
1655 | c = getc (file); | |
1656 | ||
1657 | if (c == '\n' || c == EOF) | |
1658 | return c; | |
1659 | ||
1660 | while (psize < sizeof (pbuf) - 1 && c != '\n') | |
1661 | { | |
1662 | pbuf[psize++] = c; | |
1663 | if (psize == 9 && strncmp (pbuf, "interrupt", 9) == 0) | |
1664 | { | |
1665 | pragma_interrupt = 1; | |
06c386ea | 1666 | return ' '; |
0d7e008e SC |
1667 | } |
1668 | if (psize == 5 && strncmp (pbuf, "trapa", 5) == 0) | |
1669 | { | |
1670 | pragma_interrupt = pragma_trapa = 1; | |
06c386ea | 1671 | return ' '; |
0d7e008e SC |
1672 | } |
1673 | c = getc (file); | |
1674 | } | |
1675 | return c; | |
1676 | } | |
1677 | \f | |
8aa2a305 | 1678 | /* Predicates used by the templates. */ |
0d7e008e | 1679 | |
8aa2a305 JW |
1680 | /* Returns 1 if OP is MACL, MACH or PR. The input must be a REG rtx. |
1681 | Used only in general_movsrc_operand. */ | |
0d7e008e | 1682 | |
8aa2a305 JW |
1683 | int |
1684 | system_reg_operand (op, mode) | |
1685 | rtx op; | |
1686 | enum machine_mode mode; | |
0d7e008e | 1687 | { |
8aa2a305 | 1688 | switch (REGNO (op)) |
0d7e008e | 1689 | { |
8aa2a305 JW |
1690 | case PR_REG: |
1691 | case MACL_REG: | |
1692 | case MACH_REG: | |
1693 | return 1; | |
0d7e008e | 1694 | } |
8aa2a305 | 1695 | return 0; |
0d7e008e | 1696 | } |
0d7e008e SC |
1697 | |
1698 | /* Returns 1 if OP can be source of a simple move operation. | |
1699 | Same as general_operand, but a LABEL_REF is valid, PRE_DEC is | |
16bea517 | 1700 | invalid as are subregs of system registers. */ |
0d7e008e SC |
1701 | |
1702 | int | |
1703 | general_movsrc_operand (op, mode) | |
1704 | rtx op; | |
1705 | enum machine_mode mode; | |
1706 | { | |
06c386ea SC |
1707 | if (GET_CODE (op) == MEM) |
1708 | { | |
1709 | rtx inside = XEXP (op, 0); | |
1710 | if (GET_CODE (inside) == CONST) | |
1711 | inside = XEXP (inside, 0); | |
0d7e008e | 1712 | |
06c386ea SC |
1713 | if (GET_CODE (inside) == LABEL_REF) |
1714 | return 1; | |
8e87e161 | 1715 | |
06c386ea | 1716 | if (GET_CODE (inside) == PLUS |
8aa2a305 JW |
1717 | && GET_CODE (XEXP (inside, 0)) == LABEL_REF |
1718 | && GET_CODE (XEXP (inside, 1)) == CONST_INT) | |
06c386ea | 1719 | return 1; |
16bea517 JW |
1720 | |
1721 | /* Only post inc allowed. */ | |
97f8690b | 1722 | if (GET_CODE (inside) == PRE_DEC) |
06c386ea | 1723 | return 0; |
06c386ea | 1724 | } |
0d7e008e SC |
1725 | |
1726 | if ((mode == QImode || mode == HImode) | |
1727 | && (GET_CODE (op) == SUBREG | |
1728 | && GET_CODE (XEXP (op, 0)) == REG | |
1729 | && system_reg_operand (XEXP (op, 0), mode))) | |
1730 | return 0; | |
1731 | ||
0d7e008e | 1732 | return general_operand (op, mode); |
b9654711 SC |
1733 | } |
1734 | ||
0d7e008e SC |
1735 | /* Returns 1 if OP can be a destination of a move. |
1736 | Same as general_operand, but no preinc allowed. */ | |
1737 | ||
b9654711 | 1738 | int |
0d7e008e SC |
1739 | general_movdst_operand (op, mode) |
1740 | rtx op; | |
1741 | enum machine_mode mode; | |
b9654711 | 1742 | { |
16bea517 | 1743 | /* Only pre dec allowed. */ |
97f8690b | 1744 | if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC) |
0d7e008e | 1745 | return 0; |
d3ae8277 | 1746 | |
0d7e008e SC |
1747 | return general_operand (op, mode); |
1748 | } | |
1749 | ||
0d7e008e SC |
1750 | /* Returns 1 if OP is a normal arithmetic register. */ |
1751 | ||
1752 | int | |
1753 | arith_reg_operand (op, mode) | |
1754 | rtx op; | |
1755 | enum machine_mode mode; | |
1756 | { | |
1757 | if (register_operand (op, mode)) | |
1758 | { | |
1759 | if (GET_CODE (op) == REG) | |
1760 | return (REGNO (op) != T_REG | |
07c109c8 JW |
1761 | && REGNO (op) != PR_REG |
1762 | && REGNO (op) != MACH_REG | |
1763 | && REGNO (op) != MACL_REG); | |
0d7e008e SC |
1764 | return 1; |
1765 | } | |
1766 | return 0; | |
1767 | } | |
1768 | ||
0d7e008e SC |
1769 | /* Returns 1 if OP is a valid source operand for an arithmetic insn. */ |
1770 | ||
1771 | int | |
1772 | arith_operand (op, mode) | |
1773 | rtx op; | |
1774 | enum machine_mode mode; | |
1775 | { | |
1776 | if (arith_reg_operand (op, mode)) | |
1777 | return 1; | |
1778 | ||
8aa2a305 JW |
1779 | if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I (INTVAL (op))) |
1780 | return 1; | |
1781 | ||
0d7e008e SC |
1782 | return 0; |
1783 | } | |
1784 | ||
22e1ebf1 JW |
1785 | /* Returns 1 if OP is a valid source operand for a compare insn. */ |
1786 | ||
1787 | int | |
1788 | arith_reg_or_0_operand (op, mode) | |
1789 | rtx op; | |
1790 | enum machine_mode mode; | |
1791 | { | |
1792 | if (arith_reg_operand (op, mode)) | |
1793 | return 1; | |
1794 | ||
8aa2a305 JW |
1795 | if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_N (INTVAL (op))) |
1796 | return 1; | |
1797 | ||
22e1ebf1 JW |
1798 | return 0; |
1799 | } | |
1800 | ||
16bea517 | 1801 | /* Returns 1 if OP is a valid source operand for a logical operation. */ |
0d7e008e SC |
1802 | |
1803 | int | |
1804 | logical_operand (op, mode) | |
1805 | rtx op; | |
1806 | enum machine_mode mode; | |
1807 | { | |
1808 | if (arith_reg_operand (op, mode)) | |
1809 | return 1; | |
1810 | ||
8aa2a305 JW |
1811 | if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_L (INTVAL (op))) |
1812 | return 1; | |
1813 | ||
0d7e008e | 1814 | return 0; |
b9654711 | 1815 | } |
8aa2a305 | 1816 | \f |
d3ae8277 SC |
1817 | /* Determine where to put an argument to a function. |
1818 | Value is zero to push the argument on the stack, | |
1819 | or a hard register in which to store the argument. | |
1820 | ||
1821 | MODE is the argument's machine mode. | |
1822 | TYPE is the data type of the argument (as a tree). | |
1823 | This is null for libcalls where that information may | |
1824 | not be available. | |
1825 | CUM is a variable of type CUMULATIVE_ARGS which gives info about | |
1826 | the preceding args and about the function being called. | |
1827 | NAMED is nonzero if this argument is a named parameter | |
1828 | (otherwise it is an extra parameter matching an ellipsis). */ | |
1829 | ||
8e87e161 | 1830 | rtx |
d3ae8277 | 1831 | sh_function_arg (cum, mode, type, named) |
8e87e161 SC |
1832 | CUMULATIVE_ARGS cum; |
1833 | enum machine_mode mode; | |
1834 | tree type; | |
1835 | int named; | |
d3ae8277 SC |
1836 | { |
1837 | if (named) | |
1838 | { | |
8aa2a305 | 1839 | int rr = (ROUND_REG (cum, mode)); |
d3ae8277 SC |
1840 | |
1841 | if (rr < NPARM_REGS) | |
8aa2a305 JW |
1842 | return ((type == 0 || ! TREE_ADDRESSABLE (type)) |
1843 | ? gen_rtx (REG, mode, FIRST_PARM_REG + rr) : 0); | |
d3ae8277 SC |
1844 | } |
1845 | return 0; | |
1846 | } | |
1847 | ||
1848 | /* For an arg passed partly in registers and partly in memory, | |
1849 | this is the number of registers used. | |
1850 | For args passed entirely in registers or entirely in memory, zero. | |
1851 | Any arg that starts in the first 4 regs but won't entirely fit in them | |
1852 | needs partial registers on the SH. */ | |
1853 | ||
1854 | int | |
8aa2a305 JW |
1855 | sh_function_arg_partial_nregs (cum, mode, type, named) |
1856 | CUMULATIVE_ARGS cum; | |
1857 | enum machine_mode mode; | |
1858 | tree type; | |
1859 | int named; | |
d3ae8277 | 1860 | { |
8aa2a305 | 1861 | if (cum < NPARM_REGS) |
8e87e161 | 1862 | { |
8aa2a305 JW |
1863 | if ((type == 0 || ! TREE_ADDRESSABLE (type)) |
1864 | && (cum + (mode == BLKmode | |
1865 | ? ROUND_ADVANCE (int_size_in_bytes (type)) | |
1866 | : ROUND_ADVANCE (GET_MODE_SIZE (mode))) - NPARM_REGS > 0)) | |
1867 | return NPARM_REGS - cum; | |
d3ae8277 SC |
1868 | } |
1869 | return 0; | |
1870 | } | |
a55e9d2b RK |
1871 | \f |
1872 | /* Return non-zero if REG is not used after INSN. | |
1873 | We assume REG is a reload reg, and therefore does | |
1874 | not live past labels or calls or jumps. */ | |
1875 | int | |
1876 | reg_unused_after (reg, insn) | |
1877 | rtx reg; | |
1878 | rtx insn; | |
1879 | { | |
8783b15e | 1880 | enum rtx_code code; |
a55e9d2b RK |
1881 | rtx set; |
1882 | ||
1883 | /* If the reg is set by this instruction, then it is safe for our | |
1884 | case. Disregard the case where this is a store to memory, since | |
1885 | we are checking a register used in the store address. */ | |
1886 | set = single_set (insn); | |
1887 | if (set && GET_CODE (SET_DEST (set)) != MEM | |
1888 | && reg_overlap_mentioned_p (reg, SET_DEST (set))) | |
1889 | return 1; | |
1890 | ||
1891 | while (insn = NEXT_INSN (insn)) | |
1892 | { | |
a55e9d2b | 1893 | code = GET_CODE (insn); |
8783b15e RK |
1894 | |
1895 | if (code == CODE_LABEL) | |
a55e9d2b RK |
1896 | return 1; |
1897 | ||
8783b15e RK |
1898 | /* If this is a sequence, we must handle them all at once. |
1899 | We could have for instance a call that sets the target register, | |
1900 | and a insn in a delay slot that uses the register. In this case, | |
1901 | we must return 0. */ | |
1902 | else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE) | |
a55e9d2b | 1903 | { |
8783b15e RK |
1904 | int i; |
1905 | int retval = 0; | |
1906 | ||
1907 | for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) | |
1908 | { | |
1909 | rtx this_insn = XVECEXP (PATTERN (insn), 0, i); | |
1910 | rtx set = single_set (this_insn); | |
1911 | ||
1912 | if (GET_CODE (this_insn) == CALL_INSN) | |
1913 | code = CALL_INSN; | |
a55e9d2b | 1914 | |
8783b15e RK |
1915 | if (set && reg_overlap_mentioned_p (reg, SET_SRC (set))) |
1916 | return 0; | |
1917 | if (set && reg_overlap_mentioned_p (reg, SET_DEST (set))) | |
1918 | { | |
1919 | if (GET_CODE (SET_DEST (set)) != MEM) | |
1920 | retval = 1; | |
1921 | else | |
1922 | return 0; | |
1923 | } | |
1924 | if (set == 0 | |
1925 | && reg_overlap_mentioned_p (reg, PATTERN (this_insn))) | |
1926 | return 0; | |
1927 | } | |
1928 | if (retval == 1) | |
1929 | return 1; | |
1930 | } | |
1931 | else if (GET_RTX_CLASS (code) == 'i') | |
a55e9d2b RK |
1932 | { |
1933 | rtx set = single_set (insn); | |
1934 | ||
1935 | if (set && reg_overlap_mentioned_p (reg, SET_SRC (set))) | |
1936 | return 0; | |
1937 | if (set && reg_overlap_mentioned_p (reg, SET_DEST (set))) | |
1938 | return GET_CODE (SET_DEST (set)) != MEM; | |
1939 | if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn))) | |
1940 | return 0; | |
1941 | } | |
8783b15e RK |
1942 | |
1943 | if (code == CALL_INSN && call_used_regs[REGNO (reg)]) | |
1944 | return 1; | |
a55e9d2b RK |
1945 | } |
1946 | return 1; | |
1947 | } |