|
|
1.1 root 1: /* Output routines for GCC for Hitachi Super-H
2: Copyright (C) 1993 Free Software Foundation, Inc.
3:
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
19:
20:
21: /* Contributed by Steve Chamberlain ([email protected]) */
22:
23: #include <stdio.h>
24: #include "assert.h"
25: #include "config.h"
26: #include "rtl.h"
27: #include "regs.h"
28: #include "hard-reg-set.h"
29: #include "real.h"
30: #include "insn-config.h"
31: #include "conditions.h"
32: #include "insn-flags.h"
33: #include "tree.h"
34: #include "output.h"
35: #include "insn-attr.h"
36: #include "flags.h"
37: #include "obstack.h"
38: #include "expr.h"
39:
40:
41: static int add_constant ();
42: static int dump_constants ();
43:
44: int current_function_anonymous_args;
45: extern int current_function_pretend_args_size;
46:
47: /* Global variables for machine-dependent things. */
48:
49: /* Saved operands from the last compare to use when we generate an scc
50: or bcc insn. */
51:
52: rtx sh_compare_op0;
53: rtx sh_compare_op1;
54:
55: /* Provides the class number of the smallest class containing
56: reg number */
57:
58: int regno_reg_class[FIRST_PSEUDO_REGISTER] =
59: {
60: R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
61: GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
62: GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
63: GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
64: GENERAL_REGS, PR_REGS, T_REGS, NO_REGS, MAC_REGS,
65: MAC_REGS,
66: };
67:
68: /* Provide reg_class from a letter such as appears in the machine
69: description. */
70:
71: enum reg_class reg_class_from_letter[] =
72: {
73: /* a */ NO_REGS, /* b */ NO_REGS, /* c */ NO_REGS, /* d */ NO_REGS,
74: /* e */ NO_REGS, /* f */ NO_REGS, /* g */ NO_REGS, /* h */ NO_REGS,
75: /* i */ NO_REGS, /* j */ NO_REGS, /* k */ NO_REGS, /* l */ PR_REGS,
76: /* m */ NO_REGS, /* n */ NO_REGS, /* o */ NO_REGS, /* p */ NO_REGS,
77: /* q */ NO_REGS, /* r */ NO_REGS, /* s */ NO_REGS, /* t */ T_REGS,
78: /* u */ NO_REGS, /* v */ NO_REGS, /* w */ NO_REGS, /* x */ MAC_REGS,
79: /* y */ NO_REGS, /* z */ R0_REGS
80: };
81:
82:
83: /* Local label counter, used for constants in the pool and inside
84: pattern branches. */
85:
86: static int lf = 100;
87:
88: /* Used to work out sizes of instructions */
89: static int first_pc;
90: static int pc;
91: #define MAYBE_DUMP_LEVEL 900
92: #define MUST_DUMP_LEVEL 1000
93: static int dumpnext;
94:
95: /* Functions for generating procedure prologue and epilogue code */
96:
97: /* Adjust the stack and return the number of bytes taken to do it */
98:
99: static int
100: output_stack_adjust (file, direction, size)
101: FILE *file;
102: int direction;
103: int size;
104: {
105: int code_size;
106:
107: if (size > 127)
108: {
109: fprintf (file, "\tmov.l LK%d,r13\n",
110: add_constant (GEN_INT (size * direction), SImode));
111:
112: fprintf (file, "\tadd r13,r15\n");
113: code_size += 4;
114: }
115: else if (size)
116: {
117: fprintf (file, "\tadd #%d,r15\n", direction * size);
118: code_size += 2;
119: }
120: return code_size;
121: }
122:
123: /* Generate code to push the regs specified in the mask, and return
124: the number of bytes the insns take. */
125:
126: static int
127: push_regs (f, mask)
128: FILE *f;
129: int mask;
130: {
131: int i;
132: int size = 0;
133:
134: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
135: {
136: if (mask & (1 << i))
137: {
138: fprintf (f, "\tmov.l r%d,@-r15\n", i);
139: size += 2;
140: }
141: }
142: return size;
143: }
144:
145:
146: /* Working out the right code to use for an epilogue can get quite
147: hairy, since there are only certain insns which can go in the delay
148: slot, and there may or may not be a delay insn provided already.
149:
150: We generate a canonical list of the instructions to use to perform
151: the exit, massage that and output from that list */
152:
153:
154: /* The structure of a canonical element. */
155:
156: typedef struct
157: {
158: enum epi_type
159: {
160: STACK_ADJUST, /* add i to stack pointer */
161: POP, /* pop into register i */
162: RTS, /* rts instruction */
163: DELAY, /* delay slot instruction */
164: NOP, /* a nop */
165: DELETED,
166: } type;
167: int i;
168: }
169:
170: epilogue_insn;
171:
172: static epilogue_insn epilogue_vec[20];
173: static int epilogue_vec_len;
174:
175: static void
176: set_epilogue_insn (type, l)
177: enum epi_type type;
178: int l;
179: {
180: epilogue_vec[epilogue_vec_len].type = type;
181: epilogue_vec[epilogue_vec_len].i = l;
182: epilogue_vec_len++;
183: }
184:
185: /* Delete an insn from the epilogue list. */
186:
187: static void
188: delete_epilogue_insn (n)
189: int n;
190: {
191: int j;
192:
193: for (j = n; j < epilogue_vec_len; j++)
194: epilogue_vec[j] = epilogue_vec[j + 1];
195:
196: epilogue_vec_len--;
197: }
198:
199: /* Run through the epilogue list and optimize it. */
200:
201: static void
202: optimize_epilogue_vec ()
203: {
204: int i;
205:
206: /* Turn two adds in a row into one add and kill empty adds */
207: for (i = 0; i < epilogue_vec_len - 1; i++)
208: {
209: if (epilogue_vec[i].type == STACK_ADJUST
210: && epilogue_vec[i + 1].type == STACK_ADJUST)
211: {
212: epilogue_vec[i].i += epilogue_vec[i + 1].i;
213: delete_epilogue_insn (i + 1);
214: }
215: if (epilogue_vec[i].type == STACK_ADJUST
216: && epilogue_vec[i].i == 0)
217: delete_epilogue_insn (i);
218: }
219:
220: /* If the instruction after the RTS is a nop, see if it can be
221: changed */
222:
223: for (i = 1; i < epilogue_vec_len - 1; i++)
224: {
225: if (epilogue_vec[i].type == RTS
226: && epilogue_vec[i + 1].type == NOP)
227: {
228: epilogue_vec[i + 1] = epilogue_vec[i - 1];
229: delete_epilogue_insn (i - 1);
230: }
231: }
232:
233: /* Delete all the instructions after the rts's delay slot */
234: for (i = 0; i < epilogue_vec_len; i++)
235: {
236: if (epilogue_vec[i].type == RTS)
237: {
238: int j;
239:
240: for (j = i + 2; j < epilogue_vec_len; j++)
241: epilogue_vec[j].type = DELETED;
242: return;
243: }
244: }
245: }
246:
247: /* Dump out the insns in epilogue vector. */
248:
249: static void
250: output_epilogue_vec ()
251: {
252: int i;
253:
254: for (i = 0; i < epilogue_vec_len; i++)
255: {
256: switch (epilogue_vec[i].type)
257: {
258: case STACK_ADJUST:
259: fprintf (asm_out_file, "\tadd #%d,r15\n", epilogue_vec[i].i);
260: break;
261:
262: case NOP:
263: fprintf (asm_out_file, "\tor r0,r0\n");
264: break;
265:
266: case DELAY:
267: final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
268: asm_out_file, 1, 0, 1);
269: break;
270:
271: case DELETED:
272: fprintf (asm_out_file, "\t!delete_epilogue_insnd\n");
273: break;
274:
275: case RTS:
276: fprintf (asm_out_file, "\trts\n");
277: break;
278:
279: case POP:
280: fprintf (asm_out_file, "\tmov.l @r15+,r%d\n",
281: epilogue_vec[i].i);
282: break;
283: }
284: }
285: epilogue_vec_len = 0;
286: }
287:
288: /* Number of bytes pushed for anonymous args */
289:
290: static int extra_push;
291:
292: /* Work out the registers which need to be saved, both as a mask and a
293: count */
294:
295: int
296: calc_live_regs (count)
297: int *count;
298: {
299: int reg;
300: int live_regs_mask = 0;
301: *count = 0;
302:
303: for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++)
304: {
305: if (regs_ever_live[reg] && !call_used_regs[reg])
306: {
307: (*count)++;
308: live_regs_mask |= (1 << reg);
309: }
310: }
311: return live_regs_mask;
312: }
313:
314: /* Generate a procedure prologue. */
315:
316: void
317: output_prologue (f, frame_size)
318: FILE *f;
319: int frame_size;
320: {
321: int live_regs_mask;
322: int d;
323:
324: pc = 0;
325:
326: /* This only happens when an arg has been split, part in
327: registers, part in memory. Allocate the stack space so there is
328: somewhere to put the value */
329:
330: output_stack_adjust (f, -1, current_function_pretend_args_size);
331:
332: live_regs_mask = calc_live_regs (&d);
333:
334: extra_push = 0;
335:
336: if (current_function_anonymous_args)
337: {
338: /* Push arg regs as if they'd been provided by caller in stack */
339: int i;
340: for (i = 0; i < NPARM_REGS; i++)
341: {
342: int rn = NPARM_REGS + FIRST_PARM_REG - i - 1;
343: if (i > NPARM_REGS - current_function_args_info)
344: break;
345: fprintf (f, "\tmov.l r%d,@-r15\n", rn);
346: extra_push += 4;
347: pc += 2;
348: }
349: }
350:
351: if (frame_pointer_needed)
352: {
353: /* Don't need to push the fp with the rest of the registers. */
354: live_regs_mask &= ~(1 << FRAME_POINTER_REGNUM);
355: pc += push_regs (f, live_regs_mask);
356: if (regs_ever_live[PR_REG])
357: {
358:
359: fprintf (f, "\tsts.l pr,@-r15\n");
360: pc += 2;
361: }
362:
363: fprintf (f, "\tmov.l r14,@-r15\n");
364: fprintf (f, "\tmov r15,r14\n");
365: pc += 4;
366: pc += output_stack_adjust (f, -1, frame_size);
367: }
368: else
369: {
370: pc += push_regs (f, live_regs_mask);
371:
372: if (regs_ever_live[PR_REG])
373: {
374:
375: fprintf (f, "\tsts.l pr,@-r15\n");
376: pc += 2;
377: }
378: pc += output_stack_adjust (f, -1, frame_size);
379: }
380: }
381:
382:
383: /* Generate a procedure epilogue. */
384:
385: void
386: output_epilogue (f, frame_size)
387: FILE *f;
388: int frame_size;
389: {
390: int live_regs_mask = 0;
391: int d;
392: int i;
393: rtx delay_insn;
394:
395: live_regs_mask = calc_live_regs (&d);
396:
397:
398: /* See if the delay insn is really ok for the slot. */
399: if (current_function_epilogue_delay_list) {
400: delay_insn = PATTERN (XEXP (current_function_epilogue_delay_list, 0));
401:
402: if (GET_CODE (delay_insn) == SET
403: && SET_DEST (delay_insn) == stack_pointer_rtx)
404: {
405: /* Can not use this instruction in the delay slot because
406: it changes the stack pointer, so emit it now. */
407: final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
408: asm_out_file, 1, 0, 1);
409: current_function_epilogue_delay_list = 0;
410: }
411: }
412:
413:
414: /* Reclaim the room for the automatics. */
415:
416: output_stack_adjust (f, 1, frame_size);
417:
418: /* Make the frame pointer. */
419:
420: if (frame_pointer_needed)
421: {
422: fprintf (f, "\tmov r14,r15\n");
423: fprintf (f, "\tmov.l @r15+,r14\n");
424: live_regs_mask &= ~(1 << FRAME_POINTER_REGNUM);
425: }
426:
427: /* Get the PR register if it was clobbered in the function. */
428:
429: if (regs_ever_live[PR_REG])
430: fprintf (f, "\tlds.l @r15+,pr\n");
431:
432: /* Pop all the registers */
433: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
434: {
435: int j = (FIRST_PSEUDO_REGISTER - 1) - i;
436: if (live_regs_mask & (1 << j))
437: {
438: set_epilogue_insn (POP, j);
439: }
440: }
441:
442: /* Need to adjust the stack by some amount of bytes since we've pushed
443: some of the args which normally come in registers */
444:
445: set_epilogue_insn (STACK_ADJUST, extra_push);
446:
447: /* Need to adjust the stack by some amount of bytes if there
448: an arg has been split part register and part stack */
449:
450: set_epilogue_insn (STACK_ADJUST, current_function_pretend_args_size);
451:
452: set_epilogue_insn (RTS, 0);
453:
454: /* Got here without dumping a register pop into the delay slot */
455: if (current_function_epilogue_delay_list)
456: {
457: set_epilogue_insn (DELAY, 0);
458: }
459: set_epilogue_insn (NOP, 0);
460:
461: optimize_epilogue_vec ();
462:
463: output_epilogue_vec ();
464:
465: dump_constants (0);
466: current_function_anonymous_args = 0;
467: }
468:
469: /* Print the operand address in x to the stream */
470:
471: void
472: print_operand_address (stream, x)
473: FILE *stream;
474: rtx x;
475: {
476: switch (GET_CODE (x))
477: {
478: case REG:
479: fprintf (stream, "@%s", reg_names[REGNO (x)]);
480: break;
481:
482: case PLUS:
483: {
484: rtx base = XEXP (x, 0);
485: rtx index = XEXP (x, 1);
486:
487: if (GET_CODE (base) != REG)
488: {
489: /* Ensure that BASE is a register (one of them must be). */
490: rtx temp = base;
491: base = index;
492: index = temp;
493: }
494:
495: switch (GET_CODE (index))
496: {
497: case CONST_INT:
498: fprintf (stream, "@(%d,%s)",
499: INTVAL (index),
500: reg_names[REGNO (base)]);
501: break;
502:
503: case REG:
504: fprintf (stream, "@(%s,%s)",
505: reg_names[REGNO (base)],
506: reg_names[REGNO (index)]);
507: break;
508:
509: default:
510: abort ();
511: }
512: }
513:
514: break;
515: case PRE_DEC:
516: fprintf (stream, "@-%s", reg_names[REGNO (XEXP (x, 0))]);
517: break;
518:
519: case POST_INC:
520: fprintf (stream, "@%s+", reg_names[REGNO (XEXP (x, 0))]);
521: break;
522:
523: default:
524: output_addr_const (stream, x);
525: break;
526: }
527: }
528:
529: /* Print operand x (an rtx) in assembler syntax to file stream
530: according to modifier code.
531:
532: '*' print a local label
533: '^' increment the local label number
534: '!' dump the constant table
535: '#' output a nop if there is nothing to put in the delay slot
536: 'R' print the next register or memory location along, ie the lsw in
537: a double word value
538: 'I' put something into the constant pool and print its label */
539:
540: void
541: print_operand (stream, x, code)
542: FILE *stream;
543: rtx x;
544: int code;
545: {
546: switch (code)
547: {
548: case '*':
549: fprintf (stream, "LF%d", lf);
550: break;
551: case '!':
552: dump_constants (0);
553: break;
554: case '^':
555: lf++;
556: break;
557:
558: case '#':
559: /* Output a nop if there's nothing in the delay slot */
560: if (dbr_sequence_length () == 0)
561: {
562: fprintf (stream, "\n\tor r0,r0\t!wasted slot");
563: }
564: break;
565:
566: case 'I':
567: fprintf (asm_out_file, "LK%d", add_constant (x, SImode));
568: break;
569:
570: case 'R':
571: /* Next location along in memory or register*/
572: switch (GET_CODE (x))
573: {
574: case REG:
575: fputs (reg_names[REGNO (x) + 1], (stream));
576: break;
577: case MEM:
578: print_operand_address (stream,
579: XEXP (adj_offsettable_operand (x, 4), 0), 0);
580: break;
581: }
582: break;
583:
584: default:
585: switch (GET_CODE (x))
586: {
587: case REG:
588: fputs (reg_names[REGNO (x)], (stream));
589: break;
590: case MEM:
591: output_address (XEXP (x, 0));
592: break;
593: default:
594: fputc ('#', stream);
595: output_addr_const (stream, x);
596: break;
597:
598: }
599: break;
600: }
601: }
602:
603:
604:
605: /* Define the offset between two registers, one to be eliminated, and
606: the other its replacement, at the start of a routine. */
607:
608: int
609: initial_elimination_offset (from, to)
610: {
611: int regs_saved;
612: int d = calc_live_regs (®s_saved);
613: int total_saved_regs_space = (regs_saved + regs_ever_live[PR_REG]) * 4;
614: int total_auto_space = get_frame_size ();
615:
616:
617: if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
618: {
619: return total_saved_regs_space;
620: }
621:
622: if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
623: {
624: return total_saved_regs_space + total_auto_space;
625: }
626:
627: if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
628: {
629: return total_auto_space;
630: }
631: }
632:
633: delay_slots_for_epilogue ()
634: {
635: /* We need to find something to fill the epilogue if there won't be
636: any instructions to make the stack or pop registers which can be
637: moved into the slot */
638:
639: int d;
640: calc_live_regs (&d);
641: return !(get_frame_size () + d);
642: }
643:
644:
645: /* Prepare operands for a move define_expand; specifically, one of the
646: operands must be in a register */
647:
648: void
649: prepare_move_operands (operands, mode)
650: rtx operands[];
651: enum machine_mode mode;
652: {
653: /* One of the operands has to be a register */
654: if ((!register_operand (operands[0], mode)
655: && !register_operand (operands[1], mode))
656: || GET_CODE(operands[1]) == PLUS)
657: {
658: /* copy the source to a register */
659: operands[1] = copy_to_mode_reg (mode, operands[1]);
660: }
661: }
662:
663:
664: /* Prepare the operands for an scc instruction; make sure that the
665: compare has been done. */
666: rtx
667: prepare_scc_operands (code)
668: {
669: if (GET_CODE(sh_compare_op0) != REG
670: || REGNO(sh_compare_op0) != T_REG)
671: {
672: /* First need a compare insn */
673: emit_insn (gen_rtx (SET, SImode,
674: gen_rtx (REG, SImode, T_REG),
675: gen_rtx (code, SImode, sh_compare_op0,
676: sh_compare_op1)));
677: }
678: return gen_rtx(REG, SImode, T_REG);
679: }
680:
681: /* Functions to output assembly */
682:
683: /* Return a sequence of instructions to perform DI move, taking into
684: account overlapping source and dest registers */
685:
686: char *
687: output_movedouble (operands, mode)
688: rtx operands[];
689: enum machine_mode mode;
690: {
691: if (register_operand (operands[0], mode)
692: && register_operand (operands[1], mode))
693: {
694: if (REGNO (operands[1]) == MACH_REG)
695: return "sts mach,%0\n\tsts macl,%R0";
696: if (REGNO (operands[1]) > REGNO (operands[0]))
697: {
698: return "mov %1,%0\n\tmov %R1,%R0";
699: }
700: else
701: {
702: return "mov %R1,%R0\n\tmov %1,%0";
703: }
704: }
705:
706: if (GET_CODE (operands[1]) == CONST_INT)
707: {
708: if (INTVAL (operands[1]) < 0)
709: return "mov #-1,%0\n\tmov %1,%R0";
710: else
711: return "mov #0,%0\n\tmov %1,%R0";
712: }
713:
714: if (GET_CODE (operands[1]) == MEM)
715: {
716: int idxreg = -1;
717: rtx inside = XEXP (operands[1], 0);
718:
719: if (GET_CODE (inside) == REG)
720: idxreg = REGNO (inside);
721: else if (GET_CODE (inside) == PLUS)
722: {
723: rtx lhs = XEXP (inside, 0);
724: rtx rhs = XEXP (inside, 1);
725: if (GET_CODE (lhs) == REG)
726: idxreg = REGNO (lhs);
727: else if (GET_CODE (rhs) == REG)
728: idxreg = REGNO (rhs);
729: else
730: abort ();
731: }
732: else
733: abort ();
734:
735: if (REGNO (operands[0]) != idxreg)
736: {
737: /* The dest register is mentioned in the addressing mode,
738: so print them the other way around */
739: return "mov.l %1,%0\n\tmov.l %R1,%R0 ! one way";
740: }
741: return "mov.l %R1,%R0\n\tmov.l %1,%0 ! other way";
742: }
743:
744: return "mov.l %R1,%R0\n\tmov.l %1,%0";
745: }
746:
747: /* Emit assembly to shift reg by k bits */
748:
749: char *
750: output_shift (string, reg, k)
751: char *string;
752: rtx reg;
753: rtx k;
754: {
755: int s = INTVAL (k);
756: while (s)
757: {
758: char *out;
759: int d;
760:
761: if (s >= 16)
762: {
763: d = 16;
764: out = "16";
765: }
766: else if (s >= 8)
767: {
768: d = 8;
769: out = "8";
770: }
771: else if (s >= 2)
772: {
773: d = 2;
774: out = "2";
775: }
776: else
777: {
778: d = 1;
779: out = "";
780: }
781: fprintf (asm_out_file, "\t%s%s\tr%d\n", string, out, REGNO (reg));
782: s -= d;
783: }
784: return "";
785: }
786:
787: /* Return the text of the branch instruction which matches its length
788: attribute. */
789:
790: char *
791: output_branch (logic, insn)
792: int logic;
793: rtx *insn;
794: {
795: extern rtx recog_operand[];
796: int label = lf++;
797:
798: switch (get_attr_length (insn))
799: {
800: case 2:
801: /* Simple branch in range -200..+200 bytes */
802: return logic ? "bt %l0" : "bf %l0";
803:
804: case 6:
805: /* Branch in range -4000..+4000 bytes */
806: fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label);
807: output_asm_insn ("bra %l0 ! 12 bit cond ", recog_operand);
808: fprintf (asm_out_file, "\tor r0,r0\n");
809: label = dump_constants (label);
810: fprintf (asm_out_file, "LF%d:\n", label);
811: return "";
812:
813: case 8:
814: /* Branches a long way away */
815:
816: fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label);
817: output_asm_insn ("mov.l %I0,r13", recog_operand);
818: fprintf (asm_out_file, "\tjmp @r13 ! 32 cond \n");
819: fprintf (asm_out_file, "\tor r0,r0\n");
820: fprintf (asm_out_file, "LF%d:\n", label);
821: return "";
822: }
823: return "bad";
824:
825: }
826:
827: /* Predicates used by the templates */
828:
829: /* Nonzero if OP is a normal arithmetic register. */
830:
831: int
832: arith_reg_operand(op, mode)
833: rtx op;
834: enum machine_mode mode;
835: {
836: if (register_operand (op, mode))
837: {
838: if (GET_CODE (op) == REG)
839: return REGNO (op) != T_REG;
840: return 1;
841: }
842: return 0;
843: }
844:
845:
846: /* Nonzero if OP is a valid source operand for an arithmetic insn. */
847:
848: int
849: arith_operand (op, mode)
850: rtx op;
851: enum machine_mode mode;
852: {
853: if (register_operand (op, mode))
854: return 1;
855:
856: if (GET_CODE (op) == CONST_INT)
857: {
858: if (CONST_OK_FOR_I (INTVAL (op)))
859: return 1;
860: }
861: return 0;
862: }
863:
864:
865: /* Nonzero if OP is a valid source operand for a logical operation */
866:
867: int
868: logical_operand (op, mode)
869: rtx op;
870: enum machine_mode mode;
871: {
872: if (register_operand (op, mode))
873: return 1;
874:
875: if (GET_CODE (op) == CONST_INT)
876: {
877: if (CONST_OK_FOR_L (INTVAL (op)))
878: return 1;
879: }
880: return 0;
881: }
882:
883: /* Nonzero if p is a valid shift operand for lshr and ashl */
884:
885: int
886: ok_shift_value (p)
887: rtx p;
888: {
889: if (GET_CODE (p) == CONST_INT)
890: {
891: switch (INTVAL (p))
892: {
893: case 1:
894: case 2:
895: case 8:
896: case 16:
897: return 1;
898: default:
899: if (TARGET_FASTCODE)
900: return INTVAL(p) >= 0;
901: }
902: }
903: return 0;
904: }
905:
906: /* Nonzero if the arg is an immediate which has to be loaded from
907: memory */
908:
909: int
910: hard_immediate_operand (op, mode)
911: rtx op;
912: enum machine_mode mode;
913: {
914: if (immediate_operand (op, mode))
915: {
916: if (GET_CODE (op) == CONST_INT
917: && INTVAL (op) >= -128 && INTVAL (op) < 127)
918: return 0;
919: return 1;
920: }
921: return 0;
922: }
923:
924: /* The SH cannot load a large constant into a register, constants have to
925: come from a pc relative load. The reference of a pc relative load
926: instruction must be less than 1k infront of the instruction. This
927: means that we often have to dump a constant inside a function, and
928: generate code to branch around it.
929:
930: It is important to minimize this, since the branches will slow things
931: down and make things bigger.
932:
933: Worst case code looks like:
934:
935: mov.l L1,rn
936: bra L2
937: nop
938: align
939: L1: .long value
940: L2:
941: ..
942:
943: mov.l L3,rn
944: bra L4
945: nop
946: align
947: L3: .long value
948: L4:
949: ..
950:
951: During shorten_branches we notice the instructions which can have a
952: constant table in them, if we see two that are close enough
953: together, we move the constants from the first table to the second
954: table and continue. This process can happen again and again, and
955: in the best case, moves the constant table outside of the function.
956:
957: In the above example, we can tell that L3 is within 1k of L1, so
958: the first move can be shrunk from the 3 insn+constant sequence into
959: just 1 insn, and the constant moved to L3 to make:
960:
961: mov.l L1,rn
962: ..
963: mov.l L3,rn
964: bra L4
965: nop
966: align
967: L3:.long value
968: L4:.long value
969:
970: Then the second move becomes the target for the shortening process.
971:
972: We keep a simple list of all the constants accumulated in the
973: current pool so there are no duplicates in a single table, but
974: they are not factored into the size estimates.
975:
976: */
977:
978: typedef struct
979: {
980: rtx value;
981: int number;
982: enum machine_mode mode;
983: } pool_node;
984:
985: /* The maximum number of constants that can fit into one pool, since
986: the pc relative range is 0...1020 bytes and constants are at least 4
987: bytes long */
988:
989: #define MAX_POOL_SIZE (1020/4)
990: static pool_node pool_vector[MAX_POOL_SIZE];
991: static int pool_size;
992:
993:
994: /* Add a constant to the pool and return its label number. */
995:
996: static int
997: add_constant (x, mode)
998: rtx x;
999: enum machine_mode mode;
1000: {
1001: int i;
1002:
1003: /* Start the countdown on the first constant */
1004:
1005: if (!pool_size)
1006: {
1007: first_pc = pc;
1008: }
1009:
1010: /* First see if we've already got it */
1011:
1012: for (i = 0; i < pool_size; i++)
1013: {
1014:
1015: if (x->code == pool_vector[i].value->code
1016: && mode == pool_vector[i].mode)
1017: {
1018: if (x->code == CODE_LABEL)
1019: {
1020: if (XINT (x, 3) != XINT (pool_vector[i].value, 3))
1021: continue;
1022: }
1023: }
1024:
1025: if (rtx_equal_p (x, pool_vector[i].value))
1026: return pool_vector[i].number;
1027: }
1028:
1029:
1030: pool_vector[pool_size].value = x;
1031: pool_vector[pool_size].mode = mode;
1032: pool_vector[pool_size].number = lf;
1033: pool_size++;
1034:
1035: return lf++;
1036: }
1037:
1038: /* Nonzero if the insn could take a constant table. */
1039:
1040: static int
1041: has_constant_table (insn)
1042: rtx insn;
1043: {
1044: rtx body;
1045:
1046: if (GET_CODE (insn) == NOTE
1047: || GET_CODE (insn) == BARRIER
1048: || GET_CODE (insn) == CODE_LABEL)
1049: return 0;
1050:
1051: body = PATTERN (insn);
1052: if (GET_CODE (body) == SEQUENCE)
1053: return 0;
1054: if (GET_CODE (body) == ADDR_VEC)
1055: return 0;
1056: if (GET_CODE (body) == USE)
1057: return 0;
1058: if (GET_CODE (body) == CLOBBER)
1059: return 0;
1060: if (get_attr_constneed (insn) == CONSTNEED_YES)
1061: return 1;
1062:
1063: if (GET_CODE (body) == UNSPEC_VOLATILE)
1064: {
1065: return INTVAL (XVECEXP (body, 0, 0)) == 1;
1066: }
1067: return 0;
1068: }
1069:
1070: /* Adjust the length of an instruction.
1071:
1072: We'll look at the previous instruction which holds a constant
1073: table and see if we can move the table to here instead. */
1074:
1075: int target_insn_uid;
1076: int target_insn_smallest_size;
1077:
1078: int target_pc;
1079: int target_insn_range;
1080: int current_pc;
1081: int table_size;
1082:
1083: void
1084: adjust_insn_length (insn, insn_lengths)
1085: rtx insn;
1086: short *insn_lengths;
1087: {
1088: int uid = INSN_UID (insn);
1089:
1090: current_pc += insn_lengths[uid];
1091:
1092: if (has_constant_table (insn))
1093: {
1094: if (current_pc >= target_insn_range)
1095: {
1096: /* This instruction is further away from the referencing
1097: instruction than it can reach, so we'll stop accumulating
1098: from that one and start fresh. */
1099: target_pc = current_pc;
1100: target_insn_range = current_pc + MAYBE_DUMP_LEVEL;
1101: }
1102: else
1103: {
1104: /* This instruction is within the reach of the target,
1105: remove the constant table from the target by adjusting
1106: downwards, and increase the size of this one to
1107: compensate. */
1108:
1109:
1110: /* Add the stuff from this insn to what will go in the
1111: growing table. */
1112:
1113: table_size += get_attr_constantsize (insn);
1114:
1115: /* The target shinks to its smallest natural size */
1116: insn_lengths[target_insn_uid] = target_insn_smallest_size;
1117:
1118: /* The current insn grows to be its larger size plust the
1119: table size. */
1120:
1121: insn_lengths[uid] = get_attr_largestsize (insn) + table_size;
1122:
1123: }
1124: /* Current insn becomes the target. */
1125: target_insn_uid = uid;
1126: target_insn_smallest_size = get_attr_smallestsize (insn);
1127:
1128: }
1129:
1130: }
1131:
1132:
1133: /* Dump out the pending constant pool.
1134: If label provided then insert an branch in the middle of the table
1135: */
1136:
1137: static int
1138: dump_constants (label)
1139: {
1140: int i;
1141: int rlabel = label;
1142: int size = 0;
1143:
1144: for (i = 0; i < pool_size; i++)
1145: {
1146: pool_node *p = pool_vector + i;
1147: fprintf (asm_out_file, "\n\t! constants - waited %d\n", pc - first_pc);
1148: fprintf (asm_out_file, "\t.align\t2\n");
1149: fprintf (asm_out_file, "LK%d:", p->number);
1150: size += GET_MODE_SIZE (p->mode);
1151:
1152: switch (GET_MODE_CLASS (p->mode))
1153: {
1154: case MODE_INT:
1155: case MODE_PARTIAL_INT:
1156: assemble_integer (p->value, GET_MODE_SIZE (p->mode), 1);
1157: break;
1158: case MODE_FLOAT:
1159: {
1160: union real_extract u;
1161: bcopy (&CONST_DOUBLE_LOW (p->value), &u, sizeof u);
1162: assemble_real (u.d, p->mode);
1163: }
1164: }
1165:
1166: /* After 200 bytes of table, stick in another branch */
1167: if (label && size > 200)
1168: {
1169: rlabel = lf ++;
1170: fprintf (asm_out_file,"LF%d:\tbra LF%d\n", label, rlabel);
1171: fprintf (asm_out_file,"\tor r0,r0\n");
1172: label = 0;
1173: }
1174:
1175: fprintf (asm_out_file, "\n");
1176: }
1177: pool_size = 0;
1178: current_pc = 0;
1179: target_insn_range = 0;
1180: return rlabel;
1181:
1182: }
1183:
1184:
1185: /* Emit the text to load a value from a constant table. */
1186:
1187: char *
1188: output_movepcrel (insn, operands, mode)
1189: rtx insn;
1190: rtx operands[];
1191: enum machine_mode mode;
1192: {
1193: int len = GET_MODE_SIZE (mode);
1194: int rn = REGNO (operands[0]);
1195:
1196: fprintf (asm_out_file, "\tmov.l LK%d,r%d\n",
1197: add_constant (operands[1], mode), rn);
1198:
1199: if (GET_MODE_SIZE(mode) > 4)
1200: {
1201: fprintf (asm_out_file,
1202: "\tmov.l LK%d+4,r%d\n",
1203: add_constant (operands[1], mode),
1204: rn + 1);
1205:
1206: }
1207: /* If this instruction is as small as it can be, there can be no
1208: constant table attached to it. */
1209: if (get_attr_length (insn) != get_attr_smallestsize (insn))
1210: {
1211: /* This needs a constant table */
1212: fprintf (asm_out_file, "\t!constant table start\n");
1213: fprintf (asm_out_file, "\tbra LF%d\n", lf);
1214: fprintf (asm_out_file, "\tor r0,r0 ! wasted slot\n");
1215: dump_constants (0);
1216: fprintf (asm_out_file, "LF%d:\n", lf++);
1217: fprintf (asm_out_file, "\t!constant table end\n");
1218: }
1219: return "";
1220: }
1221:
1222:
1223: /* Dump out interesting debug info */
1224:
1225: void
1226: final_prescan_insn (insn, opvec, noperands)
1227: rtx insn;
1228: rtx *opvec;
1229: int noperands;
1230: {
1231: register rtx body = PATTERN (insn);
1232:
1233: if (target_flags & ISIZE_BIT)
1234: {
1235: extern int *insn_addresses;
1236:
1237: fprintf (asm_out_file, "\n!%04x*\n",
1238: insn_addresses[INSN_UID (insn)] + 0x10);
1239:
1240: fprintf (asm_out_file, "\n!%04x %d %04x len=%d\n",
1241: pc, pool_size, first_pc, get_attr_length (insn));
1242:
1243: if (TARGET_DUMP_RTL)
1244: print_rtl (asm_out_file, body);
1245:
1246:
1247: }
1248:
1249: pc += get_attr_length (insn);
1250:
1251: if (pool_size && pc - first_pc > MUST_DUMP_LEVEL)
1252: {
1253: /* For some reason we have not dumped out a constant table, and
1254: we have emitted a lot of code. This can happen if the think
1255: which wants the table is a long conditional branch (which has no
1256: room for a constant table), and there has not been a move
1257: constant anywhere. */
1258: int label = lf++;
1259: fprintf (asm_out_file, "\t!forced constant table\n");
1260: fprintf (asm_out_file, "\tbra LF%d\n", label);
1261: fprintf (asm_out_file, "\tor r0,r0 ! wasted slot\n");
1262: label = dump_constants (label);
1263: fprintf (asm_out_file, "LF%d:\n", label);
1264: fprintf (asm_out_file, "\t!constant table end\n");
1265: }
1266:
1267: }
1268:
1269:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.