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