|
|
1.1 root 1: /* Subroutines for insn-output.c for Hitachi H8/300.
2: Copyright (C) 1992,1993 Free Software Foundation, Inc.
3:
4: Contributed by Steve Chamberlain ([email protected]) and
5: Jim Wilson ([email protected]).
6:
7: This file is part of GNU CC.
8:
9: GNU CC is free software; you can redistribute it and/or modify
10: it under the terms of the GNU General Public License as published by
11: the Free Software Foundation; either version 2, or (at your option)
12: any later version.
13:
14: GNU CC is distributed in the hope that it will be useful,
15: but WITHOUT ANY WARRANTY; without even the implied warranty of
16: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: GNU General Public License for more details.
18:
19: You should have received a copy of the GNU General Public License
20: along with GNU CC; see the file COPYING. If not, write to
21: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22:
23: #include <stdio.h>
24: #include "config.h"
25: #include "rtl.h"
26: #include "regs.h"
27: #include "hard-reg-set.h"
28: #include "real.h"
29: #include "insn-config.h"
30: #include "conditions.h"
31: #include "insn-flags.h"
32: #include "output.h"
33: #include "insn-attr.h"
34: #include "flags.h"
35: #include "recog.h"
36: #include "expr.h"
37: #include "tree.h"
38:
39: /* Forward declarations. */
40: void print_operand_address ();
41: char *index ();
42:
43: /* True if a #pragma interrupt has been seen for the current function. */
44: int pragma_interrupt;
45:
46: /* True if a #pragma saveall has been seen for the current function. */
47: int pragma_saveall;
48:
49: char *names_big[]
50: = {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7"};
51:
52: char *
53: byte_reg (x, b)
54: rtx x;
55: int b;
56: {
57: static char *names_small[]
58: = {"r0l", "r0h", "r1l", "r1h", "r2l", "r2h", "r3l", "r3h",
59: "r4l", "r4h", "r5l", "r5h", "r6l", "r6h", "r7lBAD", "r7hBAD"};
60:
61: return names_small[REGNO (x) * 2 + b];
62: }
63:
64: /* REGNO must be saved/restored across calls if this macro is true. */
65: static int
66: word_reg_used (regno)
67: int regno;
68: {
69: if (regno < 7
70: && (pragma_interrupt || pragma_saveall
71: || (regno == FRAME_POINTER_REGNUM && regs_ever_live[regno])
72: || (regs_ever_live[regno] & ! call_used_regs[regno])))
73: return 1;
74: return 0;
75: }
76:
77: /* Output assembly language to FILE for the operation OP with operand size
78: SIZE. */
79: static void
80: dosize (file, op, size, fped)
81: FILE *file;
82: char *op;
83: unsigned int size;
84: int fped;
85: {
86: switch (size)
87: {
88: case 4:
89: case 3:
90: fprintf (file, "\t%ss\t#%d,sp\n", op, 2);
91: size -= 2;
92: /* Fall through... */
93: case 2:
94: case 1:
95: fprintf (file, "\t%ss\t#%d,sp\n", op, size);
96: size = 0;
97: break;
98: case 0:
99: break;
100: default:
101: fprintf (file, "\tmov.w\t#%d,r5\n\t%s.w\tr5,sp\n", size, op);
102: size = 0;
103: break;
104: }
105: }
106:
107: /* Output assembly language code for the function prologue. */
108: static int push_order[FIRST_PSEUDO_REGISTER]
109: = {6, 5, 4, 3, 2, 1, 0, -1, -1};
110: static int pop_order[FIRST_PSEUDO_REGISTER]
111: = {0, 1, 2, 3, 4, 5, 6, -1, -1};
112:
113: /* This is what the stack looks like after the prolog of
114: a function with a frame has been set up:
115:
116: <pushed args>
117: return pc
118: fp-> old fp
119: <locals>
120: <saved register-0>
121: <saved register-1>
122: sp-> <saved register-n>
123:
124:
125: This is what the stack looks like after the prolog of
126: a function which doesn't have a frame:
127:
128: <pushed args>
129: return pc
130: <locals>
131: <saved register-0>
132: sp-> <saved register-n>
133: */
134:
135: void
136: function_prologue (file, size)
137: FILE *file;
138: int size;
139: {
140: register int mask = 0;
141: int fsize = (size + 1) & -2;
142: int idx;
143:
144: if (frame_pointer_needed)
145: {
146: /* Push the fp. */
147: fprintf (file, "\tpush\t%s\n", names_big[FRAME_POINTER_REGNUM]);
148: fprintf (file, "\tmov.w\tr7,r6\n");
149:
150: /* Leave room for the locals. */
151: dosize (file, "sub", fsize, 1);
152:
153: /* Push the rest of the registers. */
154: for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
155: {
156: int regno = push_order[idx];
157:
158: if (regno >= 0 && word_reg_used (regno)
159: && regno != FRAME_POINTER_REGNUM)
160: fprintf (file, "\tpush\t%s\n", names_big[regno]);
161: }
162: }
163: else
164: {
165: dosize (file, "sub", fsize, 0);
166: for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
167: {
168: int regno = push_order[idx];
169:
170: if (regno >= 0 && word_reg_used (regno))
171: fprintf (file, "\tpush\t%s\n", names_big[regno]);
172: }
173: }
174: }
175:
176: /* Output assembly language code for the function epilogue. */
177:
178: void
179: function_epilogue (file, size)
180: FILE *file;
181: int size;
182: {
183: register int regno;
184: register int mask = 0;
185: int fsize = (size + 1) & -2;
186: int nregs;
187: int offset;
188: int idx;
189: rtx insn = get_last_insn ();
190:
191: /* If the last insn was a BARRIER, we don't have to write any code. */
192: if (GET_CODE (insn) == NOTE)
193: insn = prev_nonnote_insn (insn);
194: if (insn && GET_CODE (insn) == BARRIER)
195: return;
196:
197: nregs = 0;
198:
199: if (frame_pointer_needed)
200: {
201: /* Pop saved registers. */
202: for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
203: {
204: regno = pop_order[idx];
205: if (regno >= 0 && regno != FRAME_POINTER_REGNUM
206: && word_reg_used (regno))
207: fprintf (file, "\tpop\t%s\n", names_big[regno]);
208: }
209: /* Deallocate locals. */
210: dosize (file, "add", fsize, 1);
211: /* Pop frame pointer. */
212: fprintf (file, "\tpop\t%s\n", names_big[FRAME_POINTER_REGNUM]);
213: }
214: else
215: {
216: /* Deallocate locals and pop saved registers. */
217: for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
218: {
219: regno = pop_order[idx];
220: if (regno >= 0 && word_reg_used (regno))
221: fprintf (file, "\tpop\t%s\n", names_big[regno]);
222: }
223: dosize (file, "add", fsize, 0);
224: }
225: if (pragma_interrupt)
226: fprintf (file, "\trte\n");
227: else
228: fprintf (file, "\trts\n");
229:
230: pragma_interrupt = 0;
231: pragma_saveall = 0;
232: }
233:
234: /* Return true if VALUE is a valid constant for constraint 'P'. */
235:
236: int
237: potl8 (value)
238: {
239: switch (value)
240: {
241: case 1:
242: case 2:
243: case 4:
244: case 8:
245: case 16:
246: case 32:
247: case 64:
248: case 128:
249: return 1;
250: }
251: return 0;
252: }
253:
254: /* Return true if VALUE is a valid constant for constraint 'O'. */
255: int
256: potg8 (value)
257: int value;
258: {
259: switch (value)
260: {
261: case 256:
262: case 512:
263: case 1024:
264: case 2048:
265: case 4096:
266: case 8192:
267: case 16384:
268: case 32768:
269: return 1;
270: }
271: return 0;
272: }
273:
274: /* Return true is OP is a valid source operand for an integer move
275: instruction. */
276: int
277: general_operand_src (op, mode)
278: rtx op;
279: enum machine_mode mode;
280: {
281: /* We can't have a pre-dec as a source. */
282: if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == PRE_DEC)
283: return 0;
284: return general_operand (op, mode);
285: }
286:
287: /* Return true if OP is a valid destination operand for an integer move
288: instruction. */
289: int
290: general_operand_dst (op, mode)
291: rtx op;
292: enum machine_mode mode;
293: {
294: /* We can't have a post-inc as a dest. */
295: if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC)
296: return 0;
297: return general_operand (op, mode);
298: }
299:
300: /* Handle machine specific pragmas for compatibility with existing
301: compilers for the H8/300
302:
303: pragma saveall generates prolog/epilog code which saves and
304: restores all the registers on function entry.
305:
306: pragma interrupt saves and restores all registers, and exits with
307: an rte instruction rather than an rts. A pointer to a function
308: with this attribute may be safely used in an interrupt vector. */
309: int
310: handle_pragma (file)
311: FILE *file;
312: {
313: int c;
314: char pbuf[20];
315: int psize;
316:
317: c = getc (file);
318: while (c == ' ' || c == '\t')
319: c = getc (file);
320:
321: if (c == '\n' || c == EOF)
322: return c;
323:
324: for (psize = 0; psize < sizeof (pbuf) - 1 && isalpha (c); psize++)
325: {
326: pbuf[psize] = c;
327: c = getc (file);
328: }
329:
330: pbuf[psize] = 0;
331:
332: if (strcmp (pbuf, "interrupt") == 0)
333: pragma_interrupt = 1;
334:
335: if (strcmp (pbuf, "saveall") == 0)
336: pragma_saveall = 1;
337:
338: return c;
339: }
340:
341: /* If the next arg with MODE and TYPE is to be passed in a register, return
342: the rtx to represent where it is passed. CUM represents the state after
343: the last argument. NAMED is not used. */
344:
345: rtx
346: function_arg (cum, mode, type, named)
347: CUMULATIVE_ARGS *cum;
348: enum machine_mode mode;
349: tree type;
350: int named;
351: {
352: rtx result = 0;
353: int libcall = 0;
354:
355: /* Right now reload has a problem with reg passing with small reg
356: classes. */
357:
358: if (cum->libcall || (named && TARGET_QUICKCALL))
359: libcall = 1;
360:
361: if (TARGET_NOQUICK)
362: libcall = 0;
363:
364: if (mode != VOIDmode && libcall && mode != DFmode && mode != SFmode)
365: {
366: switch (cum->nbytes)
367: {
368: case 0:
369: result = gen_rtx (REG, mode, 0);
370: break;
371: case 2:
372: result = gen_rtx (REG, mode, 1);
373: break;
374: case 4:
375: result = gen_rtx (REG, mode, 4);
376: break;
377: case 6:
378: result = gen_rtx (REG, mode, 5);
379: break;
380: default:
381: return 0;
382: }
383: }
384: return result;
385: }
386:
387: /* Documentation for the machine specific operand escapes:
388:
389: 'C' print (operand - 2).
390: 'E' low byte of reg or -ve lsb of constant
391: 'F' high byte of reg of -ve msb of constant
392:
393: 'G' negate constant
394: 'L' fake label, changed after used twice.
395: 'M' turn a 'M' constant into its negative mod 2.
396: 'T' print operand as a word
397: 'V' print log2 of constant - used for bset instructions
398: 'X' 8 bit register or other operand
399:
400: 'Y' print either l or h depending on whether last 'Z' operand < 8 or >= 8.
401: 'Z' print int & 7
402:
403: 'e' first word of 32 bit value
404: 'f' second word of 32 bit value
405:
406: 'j' print operand as condition code.
407: 'k' print operand as reverse condition code.
408:
409: 's' low byte of 16 bit value
410: 't' high byte of 16 bit value
411:
412: 'w' 1st byte of 32 bit value zzzzzzzz yyyyyyyy xxxxxxxx wwwwwwww
413: 'x' 2nd byte of 32 bit value
414: 'y' 3rd byte of 32 bit value
415: 'z' 4th byte of 32 bit value
416:
417: */
418:
419: /* Return assembly language string which identifies a comparison type. */
420:
421: char *
422: cond_string (code)
423: enum rtx_code code;
424: {
425: switch (code)
426: {
427: case NE:
428: return "ne";
429: case EQ:
430: return "eq";
431: case GE:
432: return "ge";
433: case GT:
434: return "gt";
435: case LE:
436: return "le";
437: case LT:
438: return "lt";
439: case GEU:
440: return "hs";
441: case GTU:
442: return "hi";
443: case LEU:
444: return "ls";
445: case LTU:
446: return "lo";
447: default:
448: abort ();
449: }
450: }
451:
452: /* Print operand X using operand code CODE to assembly language output file
453: FILE. */
454:
455: void
456: print_operand (file, x, code)
457: FILE *file;
458: rtx x;
459: int code;
460: {
461: /* This is used to general unique labels for the 'L' code. */
462: static int lab = 1000;
463:
464: /* This is used for communication between the 'P' and 'U' codes. */
465: static char *last_p;
466:
467: /* This is used for communication between the 'Z' and 'Y' codes. */
468: static int bitint;
469:
470: switch (code)
471: {
472: case 'L':
473: /* 'L' must always be used twice in a single pattern. It generates
474: the same lable twice, and then will generate a unique label the
475: next time it is used. */
476: asm_fprintf (file, "tl%d", (lab++) / 2);
477: break;
478:
479: case 'X':
480: if (GET_CODE (x) == REG)
481: fprintf (file, "%s", byte_reg (x, 0));
482: else
483: goto def;
484: break;
485:
486: case 'G':
487: if (GET_CODE (x) != CONST_INT)
488: abort ();
489: fprintf (file, "#%d", 0xff & (-INTVAL (x)));
490: break;
491:
492: case 'T':
493: if (GET_CODE (x) == REG)
494: fprintf (file, "%s", names_big[REGNO (x)]);
495: else
496: goto def;
497: break;
498:
499: case 'w':
500: if (GET_CODE (x) == CONST_INT)
501: fprintf (file, "#%d", INTVAL (x) & 0xff);
502: else
503: fprintf (file, "%s", byte_reg (x, 2));
504: break;
505:
506: case 'x':
507: if (GET_CODE (x) == CONST_INT)
508: fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff);
509: else
510: fprintf (file, "%s", byte_reg (x, 3));
511: break;
512:
513: case 'y':
514: if (GET_CODE (x) == CONST_INT)
515: fprintf (file, "#%d", (INTVAL (x) >> 16) & 0xff);
516: else
517: fprintf (file, "%s", byte_reg (x, 0));
518: break;
519:
520: case 'z':
521: if (GET_CODE (x) == CONST_INT)
522: fprintf (file, "#%d", (INTVAL (x) >> 24) & 0xff);
523: else
524: fprintf (file, "%s", byte_reg (x, 1));
525: break;
526:
527: /* FOR 16 bits. */
528: case 't':
529: if (GET_CODE (x) == CONST_INT)
530: fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff);
531: else
532: fprintf (file, "%s", byte_reg (x, 1));
533: break;
534:
535: case 's':
536: if (GET_CODE (x) == CONST_INT)
537: fprintf (file, "#%d", (INTVAL (x)) & 0xff);
538: else
539: fprintf (file, "%s", byte_reg (x, 0));
540: break;
541:
542: case 'u':
543: if (GET_CODE (x) != CONST_INT)
544: abort ();
545: fprintf (file, "%d", INTVAL (x));
546: break;
547:
548: case 'Z':
549: bitint = INTVAL (x);
550: fprintf (file, "#%d", bitint & 7);
551: break;
552:
553: case 'Y':
554: fprintf (file, "%c", bitint > 7 ? 'h' : 'l');
555: break;
556:
557: case 'O':
558: bitint = exact_log2 ((~INTVAL (x)) & 0xff);
559: if (bitint == -1)
560: abort ();
561: fprintf (file, "#%d", bitint & 7);
562: break;
563:
564: case 'V':
565: bitint = exact_log2 (INTVAL (x));
566: if (bitint == -1)
567: abort ();
568: fprintf (file, "#%d", bitint & 7);
569: break;
570:
571: case 'P':
572: if (REGNO (XEXP (XEXP (x, 0), 0)) == STACK_POINTER_REGNUM)
573: {
574: last_p = "";
575: fprintf (file, ".w");
576: }
577: else
578: {
579: last_p = "l";
580: fprintf (file, ".b");
581: }
582: break;
583:
584: case 'U':
585: fprintf (file, "%s%s", names_big[REGNO (x)], last_p);
586: break;
587:
588: case 'M':
589: /* For -4 and -2, the other 2 is handled separately. */
590: switch (INTVAL (x))
591: {
592: case -2:
593: case -4:
594: fprintf (file, "#2");
595: break;
596: case -1:
597: case -3:
598: fprintf (file, "#1");
599: break;
600:
601: default:
602: abort ();
603: }
604: break;
605:
606: case 'e':
607: switch (GET_CODE (x))
608: {
609: case REG:
610: fprintf (file, "%s", names_big[REGNO (x)]);
611: break;
612: case MEM:
613: x = adj_offsettable_operand (x, 0);
614: print_operand (file, x, 0);
615: break;
616: case CONST_INT:
617: fprintf (file, "#%d", ((INTVAL (x) >> 16) & 0xffff));
618: break;
619: default:
620: abort ();
621: break;
622: }
623: break;
624:
625: case 'f':
626: switch (GET_CODE (x))
627: {
628: case REG:
629: fprintf (file, "%s", names_big[REGNO (x) + 1]);
630: break;
631:
632: case MEM:
633: x = adj_offsettable_operand (x, 2);
634: print_operand (file, x, 0);
635: break;
636:
637: case CONST_INT:
638: fprintf (file, "#%d", INTVAL (x) & 0xffff);
639: break;
640:
641: default:
642: abort ();
643: }
644: break;
645:
646: case 'C':
647: fprintf (file, "#%d", INTVAL (x) - 2);
648: break;
649:
650: case 'E':
651: switch (GET_CODE (x))
652: {
653: case REG:
654: fprintf (file, "%sl", names_big[REGNO (x)]);
655: break;
656:
657: case CONST_INT:
658: fprintf (file, "#%d", (-INTVAL (x)) & 0xff);
659: break;
660:
661: default:
662: abort ();
663: }
664: break;
665:
666: case 'F':
667: switch (GET_CODE (x))
668: {
669: case REG:
670: fprintf (file, "%sh", names_big[REGNO (x)]);
671: break;
672:
673: case CONST_INT:
674: fprintf (file, "#%d", ((-INTVAL (x)) & 0xff00) >> 8);
675: break;
676:
677: default:
678: abort ();
679: }
680: break;
681:
682: case 'j':
683: asm_fprintf (file, cond_string (GET_CODE (x)));
684: break;
685:
686: case 'k':
687: asm_fprintf (file, cond_string (reverse_condition (GET_CODE (x))));
688: break;
689: def: ;
690: default:
691: switch (GET_CODE (x))
692: {
693: case REG:
694: fprintf (file, "%s", names_big[REGNO (x)]);
695: break;
696:
697: case MEM:
698: fprintf (file, "@");
699: output_address (XEXP (x, 0));
700: break;
701:
702: case CONST_INT:
703: case SYMBOL_REF:
704: case CONST:
705: case LABEL_REF:
706: fprintf (file, "#");
707: print_operand_address (file, x);
708: break;
709: }
710: }
711: }
712:
713: /* Output assembly language output for the address ADDR to FILE. */
714:
715: void
716: print_operand_address (file, addr)
717: FILE *file;
718: rtx addr;
719: {
720: switch (GET_CODE (addr))
721: {
722: case REG:
723: fprintf (file, "%s", names_big[REGNO (addr)]);
724: break;
725:
726: case PRE_DEC:
727: fprintf (file, "-%s", names_big[REGNO (XEXP (addr, 0))]);
728: break;
729:
730: case POST_INC:
731: fprintf (file, "%s+", names_big[REGNO (XEXP (addr, 0))]);
732: break;
733:
734: case PLUS:
735: fprintf (file, "(");
736: if (GET_CODE (XEXP (addr, 0)) == REG)
737: {
738: /* reg,foo */
739: print_operand_address (file, XEXP (addr, 1));
740: fprintf (file, ",");
741: print_operand_address (file, XEXP (addr, 0));
742: }
743: else
744: {
745: /* foo+k */
746: print_operand_address (file, XEXP (addr, 0));
747: fprintf (file, "+");
748: print_operand_address (file, XEXP (addr, 1));
749: }
750: fprintf (file, ")");
751: break;
752:
753: case CONST_INT:
754: if (INTVAL (addr) < 0)
755: {
756: int v = -INTVAL (addr);
757:
758: fprintf (file, "-%d", v);
759: }
760: else
761: fprintf (file, "%d", INTVAL (addr));
762: break;
763:
764: default:
765: output_addr_const (file, addr);
766: break;
767: }
768: }
769:
770: /* Output to FILE a reference to the user-level label NAME.
771: Strip off the section name if any. It is separated from the label name
772: by a space. */
773:
774: void
775: asm_output_labelref (file, name)
776: FILE *file;
777: char *name;
778: {
779: char *p;
780:
781: fputc ('_', file);
782:
783: for (p = name; *p; p++)
784: {
785: if (*p == ' ')
786: {
787: /* If we found a space in the name, then we've skipped over the
788: section encoding. */
789: fputs (p + 1, file);
790: return;
791: }
792: }
793:
794: /* No space, so no section. */
795: fputs (name, file);
796: }
797:
798: /* Output all insn addresses and their sizes into the assembly language
799: output file. This is helpful for debugging whether the length attributes
800: in the md file are correct. This is not meant to be a user selectable
801: option. */
802:
803: void
804: final_prescan_insn (insn, operand, num_operands)
805: rtx insn, *operand;
806: int num_operands;
807: {
808: /* This holds the last insn address. */
809: static int last_insn_address = 0;
810:
811: int uid = INSN_UID (insn);
812:
813: if (TARGET_ADDRESSES)
814: {
815: fprintf (asm_out_file, "; %d %d\n", insn_addresses[uid],
816: insn_addresses[uid] - last_insn_address);
817: last_insn_address = insn_addresses[uid];
818: }
819: }
820:
821: static void
822: shift_n_bits (lval, operand, f, notzero)
823: rtx lval;
824: rtx operand;
825: rtx (*f) ();
826: int notzero;
827: {
828: rtx label = gen_label_rtx ();
829: rtx bot = gen_label_rtx ();
830:
831: if (! notzero)
832: {
833: /* Have to put a zero test at the top. */
834: emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, lval));
835: emit_jump_insn (gen_beq (bot));
836: }
837: emit_label (label);
838: f (operand);
839: emit_insn (gen_rtx (SET, QImode, lval,
840: gen_rtx (MINUS, QImode, lval, const1_rtx)));
841: emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, lval));
842: emit_jump_insn (gen_bne (label));
843:
844: emit_label (bot);
845: /* We can't end an expand with a label. */
846: emit_move_insn (operand, operand);
847: }
848:
849: int
850: can_shift (code, operands, f, limit, fby_eight)
851: int code;
852: rtx operands[];
853: rtx (*f) ();
854: int limit;
855: rtx (*fby_eight) ();
856: {
857: extern int rtx_equal_function_value_matters;
858:
859: emit_move_insn (operands[0], operands[1]);
860:
861: if (GET_CODE (operands[2]) != CONST_INT)
862: {
863: rtx lval;
864:
865: /* Can't define expand a loop after rtl generation. */
866: if (! rtx_equal_function_value_matters)
867: return 0;
868:
869: lval = gen_reg_rtx (QImode);
870:
871: convert_move (lval, operands[2], 1);
872: shift_n_bits (lval, operands[0], f, 0);
873: }
874: else
875: {
876: int i;
877:
878: i = INTVAL (operands[2]);
879: if (i >= 8 && fby_eight)
880: {
881: fby_eight (operands[0]);
882: i -= 8;
883: }
884: if (i > limit)
885: {
886: rtx lval;
887:
888: /* Can't define expand a loop after rtl generation. */
889: if (! rtx_equal_function_value_matters)
890: return 0;
891: lval = gen_reg_rtx (QImode);
892: emit_move_insn (lval, gen_rtx (CONST_INT, VOIDmode, i));
893: shift_n_bits (lval, operands[0], f, 1);
894: }
895: else
896: {
897: while (i--)
898: f (operands[0]);
899: }
900: }
901: return 1;
902: }
903:
904: int
905: domovsi (operands)
906: rtx operands[];
907: {
908: rtx src = operands[1];
909: rtx dst = operands[0];
910:
911: if (push_operand (dst, GET_MODE (dst)))
912: {
913: /* Source must be a reg. */
914: if (! REG_P (src))
915: {
916: rtx tmp = gen_reg_rtx (GET_MODE (dst));
917:
918: emit_move_insn (tmp, src);
919: operands[1] = tmp;
920: }
921: }
922: return 0;
923: }
924:
925: int
926: io (FROM, TO)
927: {
928: int OFFSET = 0;
929:
930: if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM)
931: (OFFSET) = 2 + frame_pointer_needed * 2;
932: else
933: {
934: int regno;
935: int offset = 0;
936:
937: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
938: if ((regs_ever_live[regno]
939: && (! call_used_regs[regno] || regno == FRAME_POINTER_REGNUM)))
940: offset += 2;
941:
942: (OFFSET) = offset + get_frame_size ();
943:
944: if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM)
945: (OFFSET) += 2; /* Skip saved PC. */
946: }
947: return OFFSET;
948: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.