|
|
1.1 root 1: /* Subroutines for assembler code output on the DSP1610.
2: Copyright (C) 1994 Free Software Foundation, Inc.
3: Contributed by Michael Collison ([email protected]).
4:
5: This file is part of GNU CC.
6:
7: GNU CC is free software; you can redistribute it and/or modify
8: it under the terms of the GNU General Public License as published by
9: the Free Software Foundation; either version 2, or (at your option)
10: any later version.
11:
12: GNU CC is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with GNU CC; see the file COPYING. If not, write to
19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20:
21: /* Some output-actions in dsp1600.md need these. */
22: #include <stdio.h>
23: #include "config.h"
24: #include "rtl.h"
25: #include "regs.h"
26: #include "hard-reg-set.h"
27: #include "real.h"
28: #include "insn-config.h"
29: #include "conditions.h"
30: #include "insn-flags.h"
31: #include "output.h"
32: #include "insn-attr.h"
33: #include "tree.h"
34: #include "expr.h"
35: #include "flags.h"
36:
37: char *text_seg_name;
38: char *rsect_text;
39: char *data_seg_name;
40: char *rsect_data;
41: char *bss_seg_name;
42: char *rsect_bss;
43: char *const_seg_name;
44: char *rsect_const;
45:
46: char *chip_name;
47: char *save_chip_name;
48:
49: /* Save the operands of a compare. The 16xx has not lt or gt, so
50: in these cases we swap the operands and reverse the condition */
51:
52: rtx dsp16xx_compare_op0;
53: rtx dsp16xx_compare_op1;
54: struct rtx_def *(*dsp16xx_compare_gen)();
55:
56: static char *fp;
57: static char *sp;
58: static char *rr;
59: static char *a1h;
60:
61: struct dsp16xx_frame_info current_frame_info;
62: struct dsp16xx_frame_info zero_frame_info;
63:
64: rtx dsp16xx_addhf3_libcall = (rtx) 0;
65: rtx dsp16xx_subhf3_libcall = (rtx) 0;
66: rtx dsp16xx_mulhf3_libcall = (rtx) 0;
67: rtx dsp16xx_divhf3_libcall = (rtx) 0;
68: rtx dsp16xx_cmphf3_libcall = (rtx) 0;
69: rtx dsp16xx_fixhfhi2_libcall = (rtx) 0;
70: rtx dsp16xx_floathihf2_libcall = (rtx) 0;
71: rtx dsp16xx_neghf2_libcall = (rtx) 0;
72:
73: rtx dsp16xx_mulhi3_libcall = (rtx) 0;
74: rtx dsp16xx_udivqi3_libcall = (rtx) 0;
75: rtx dsp16xx_udivhi3_libcall = (rtx) 0;
76: rtx dsp16xx_divqi3_libcall = (rtx) 0;
77: rtx dsp16xx_divhi3_libcall = (rtx) 0;
78: rtx dsp16xx_modqi3_libcall = (rtx) 0;
79: rtx dsp16xx_modhi3_libcall = (rtx) 0;
80: rtx dsp16xx_umodqi3_libcall = (rtx) 0;
81: rtx dsp16xx_umodhi3_libcall = (rtx) 0;
82: rtx dsp16xx_ashrhi3_libcall = (rtx) 0;
83: rtx dsp16xx_ashlhi3_libcall = (rtx) 0;
84: rtx dsp16xx_ucmphi2_libcall = (rtx) 0;
85: rtx dsp16xx_lshrhi3_libcall = (rtx) 0;
86:
87: char *himode_reg_name[] = HIMODE_REGISTER_NAMES;
88:
89: #define SHIFT_INDEX_1 0
90: #define SHIFT_INDEX_4 1
91: #define SHIFT_INDEX_8 2
92: #define SHIFT_INDEX_16 3
93:
94: static char *ashift_right_asm[] =
95: {
96: "%0=%0>>1",
97: "%0=%0>>4",
98: "%0=%0>>8",
99: "%0=%0>>16"
100: };
101:
102: static char *ashift_right_asm_first[] =
103: {
104: "%0=%1>>1",
105: "%0=%1>>4",
106: "%0=%1>>8",
107: "%0=%1>>16"
108: };
109:
110: static char *ashift_left_asm[] =
111: {
112: "%0=%0<<1",
113: "%0=%0<<4",
114: "%0=%0<<8",
115: "%0=%0<<16"
116: };
117:
118: static char *ashift_left_asm_first[] =
119: {
120: "%0=%1<<1",
121: "%0=%1<<4",
122: "%0=%1<<8",
123: "%0=%1<<16"
124: };
125:
126: static char *lshift_right_asm[] =
127: {
128: "%0=%0>>1\n\t%0=%b0&0x7fff",
129: "%0=%0>>4\n\t%0=%b0&0x0fff",
130: "%0=%0>>8\n\t%0=%b0&0x00ff",
131: "%0=%0>>16\n\t%0=%b0&0x0000"
132: };
133:
134: static char *lshift_right_asm_first[] =
135: {
136: "%0=%1>>1\n\t%0=%b0&0x7fff",
137: "%0=%1>>4\n\t%0=%b0&0x0fff",
138: "%0=%1>>8\n\t%0=%b0&0x00ff",
139: "%0=%1>>16\n\t%0=%b0&0x0000"
140: };
141:
142: int
143: hard_regno_mode_ok (regno, mode)
144: int regno;
145: enum machine_mode mode;
146: {
147: switch ((int) mode)
148: {
149: case VOIDmode:
150: return 1;
151:
152: /*
153: We can't use the c0-c2 for QImode, since they are only
154: 8 bits in length */
155:
156: case QImode:
157: if (regno != REG_C0 && regno != REG_C1 && regno != REG_C2)
158: return 1;
159: else
160: return 0;
161:
162: /* We only allow a0, a1, y, and p to be allocated for 32-bit modes.
163: Additionally we allow the virtual ybase registers to be used for 32-bit
164: modes. */
165:
166: case HFmode:
167: case SFmode:
168: case DFmode:
169: case XFmode:
170: case HImode:
171: case SImode:
172: case DImode:
173: if (regno == REG_A0 || regno == REG_A1 || regno == REG_Y || regno == REG_PROD
174: || (IS_YBASE_REGISTER_WINDOW(regno) && ((regno & 1) == 0)))
175: return 1;
176: else
177: return 0;
178:
179: default:
180: return 0;
181: }
182: }
183:
184: enum reg_class
185: dsp16xx_reg_class_from_letter (c)
186: int c;
187: {
188: switch (c)
189: {
190: case 'A':
191: return ACCUM_REGS;
192:
193: case 'h':
194: return ACCUM_HIGH_REGS;
195:
196: case 'j':
197: return A0H_REG;
198:
199: case 'k':
200: return A0L_REG;
201:
202: case 'q':
203: return A1H_REG;
204:
205: case 'u':
206: return A1L_REG;
207:
208: case 'x':
209: return X_REG;
210:
211: case 'y':
212: return YH_REG;
213:
214: case 'z':
215: return YL_REG;
216:
217: case 't':
218: return P_REG;
219:
220: case 'Z':
221: return Y_OR_P_REGS;
222:
223: case 'd':
224: return ACCUM_Y_OR_P_REGS;
225:
226: case 'C':
227: return NO_FRAME_Y_ADDR_REGS;
228:
229: case 'a':
230: return Y_ADDR_REGS;
231:
232: case 'B':
233: return (TARGET_BMU ? BMU_REGS : NO_REGS);
234:
235: case 'Y':
236: return YBASE_VIRT_REGS;
237:
238: case 'v':
239: return PH_REG;
240:
241: case 'w':
242: return PL_REG;
243:
244: case 'W':
245: return J_REG;
246:
247: case 'e':
248: return YBASE_ELIGIBLE_REGS;
249:
250: case 'b':
251: return ACCUM_LOW_REGS;
252:
253: case 'c':
254: return NON_YBASE_REGS;
255:
256: case 'f':
257: return Y_REG;
258:
259: case 'D':
260: return SLOW_MEM_LOAD_REGS;
261:
262: default:
263: fatal ("Illegal register class letter %c", c);
264: return NO_REGS;
265: }
266: }
267: /* Return the class number of the smallest class containing
268: reg number REGNO. */
269:
270: int
271: regno_reg_class(regno)
272: int regno;
273: {
274: switch (regno)
275: {
276: case REG_A0L:
277: return (int) A0L_REG;
278: case REG_A1L:
279: return (int) A1L_REG;
280:
281: case REG_A0:
282: return (int) A0H_REG;
283: case REG_A1:
284: return (int) A1H_REG;
285:
286: case REG_X:
287: return (int) X_REG;
288:
289: case REG_Y:
290: return (int) YH_REG;
291: case REG_YL:
292: return (int) YL_REG;
293:
294: case REG_PROD:
295: return (int) PH_REG;
296: case REG_PRODL:
297: return (int) PL_REG;
298:
299: case REG_R0: case REG_R1: case REG_R2: case REG_R3:
300: return (int) Y_ADDR_REGS;
301:
302: case REG_J:
303: return (int) J_REG;
304: case REG_K:
305: return (int) GENERAL_REGS;
306:
307: case REG_YBASE:
308: return (int) GENERAL_REGS;
309:
310: case REG_PT:
311: return (int) GENERAL_REGS;
312:
313: case REG_AR0: case REG_AR1: case REG_AR2: case REG_AR3:
314: return (int) BMU_REGS;
315:
316: case REG_C0: case REG_C1: case REG_C2:
317: return (int) GENERAL_REGS;
318:
319: case REG_PR:
320: return (int) GENERAL_REGS;
321:
322: case REG_RB:
323: return (int) GENERAL_REGS;
324:
325: case REG_YBASE0: case REG_YBASE1: case REG_YBASE2: case REG_YBASE3:
326: case REG_YBASE4: case REG_YBASE5: case REG_YBASE6: case REG_YBASE7:
327: case REG_YBASE8: case REG_YBASE9: case REG_YBASE10: case REG_YBASE11:
328: case REG_YBASE12: case REG_YBASE13: case REG_YBASE14: case REG_YBASE15:
329: case REG_YBASE16: case REG_YBASE17: case REG_YBASE18: case REG_YBASE19:
330: case REG_YBASE20: case REG_YBASE21: case REG_YBASE22: case REG_YBASE23:
331: case REG_YBASE24: case REG_YBASE25: case REG_YBASE26: case REG_YBASE27:
332: case REG_YBASE28: case REG_YBASE29: case REG_YBASE30: case REG_YBASE31:
333: return (int) YBASE_VIRT_REGS;
334:
335: default:
336: return (int) NO_REGS;
337: }
338: }
339:
340: /* A C expression for the maximum number of consecutive registers of class CLASS
341: needed to hold a value of mode MODE */
342:
343: int
344: class_max_nregs(class, mode)
345: enum reg_class class;
346: enum machine_mode mode;
347: {
348: return (GET_MODE_SIZE(mode));
349: }
350:
351: enum reg_class
352: limit_reload_class (mode, class)
353: enum machine_mode mode;
354: enum reg_class class;
355: {
356: switch ((int) class)
357: {
358: case NO_REGS:
359: case A0H_REG:
360: case A0L_REG:
361: case A0_REG:
362: case A1H_REG:
363: return class;
364:
365: case ACCUM_HIGH_REGS:
366: fatal ("ACCUM_HIGH_REGS class in limit_reload_class");
367:
368: case A1L_REG:
369: case ACCUM_LOW_REGS:
370: case A1_REG:
371: return class;
372:
373: case ACCUM_REGS:
374: if (GET_MODE_SIZE(mode) == 1)
375: return ACCUM_LOW_REGS;
376: else
377: return class;
378:
379: case X_REG:
380: case X_OR_ACCUM_LOW_REGS:
381: return class;
382:
383: case X_OR_ACCUM_REGS:
384: if (GET_MODE_SIZE(mode) == 1)
385: return X_OR_ACCUM_LOW_REGS;
386: else
387: return class;
388:
389: case YH_REG:
390: return class;
391:
392: case YH_OR_ACCUM_HIGH_REGS:
393: fatal ("YH_OR_ACCUM_HIGH_REGS found in limit_reload_class");
394:
395: case X_OR_YH_REGS:
396: return class;
397:
398: case YL_REG:
399: /* Register 'yl' is illegal for QImode, so we should never
400: see it. */
401:
402: fatal ("YL found in limit_reload_class");
403:
404: case YL_OR_ACCUM_LOW_REGS:
405: case X_OR_YL_REGS:
406: return class;
407:
408: case Y_REG:
409: if (GET_MODE_SIZE(mode) > 1)
410: return class;
411: else
412: return YH_REG;
413:
414: case ACCUM_OR_Y_REGS:
415: if (GET_MODE_SIZE(mode) > 1)
416: return class;
417: else
418: return YL_OR_ACCUM_LOW_REGS;
419:
420: case PH_REG:
421: case X_OR_PH_REGS:
422: case PL_REG:
423: case PL_OR_ACCUM_LOW_REGS:
424: case X_OR_PL_REGS:
425: return class;
426:
427: case P_REG:
428: if (GET_MODE_SIZE(mode) > 1)
429: return class;
430: else
431: return PL_REG;
432:
433: case ACCUM_OR_P_REGS:
434: if (GET_MODE_SIZE(mode) > 1)
435: return class;
436: else
437: return PL_OR_ACCUM_LOW_REGS;
438:
439: case YL_OR_P_REGS:
440: case ACCUM_LOW_OR_YL_OR_P_REGS:
441: return class;
442:
443: case Y_OR_P_REGS:
444: return class;
445:
446: case ACCUM_Y_OR_P_REGS:
447: if (GET_MODE_SIZE(mode) > 1)
448: return class;
449: else
450: return ACCUM_LOW_OR_YL_OR_P_REGS;
451:
452: case NO_FRAME_Y_ADDR_REGS:
453: case Y_ADDR_REGS:
454: case ACCUM_LOW_OR_Y_ADDR_REGS:
455: return class;
456:
457: case ACCUM_OR_Y_ADDR_REGS:
458: if (GET_MODE_SIZE(mode) > 1)
459: return ACCUM_REGS;
460: else
461: return ACCUM_LOW_OR_Y_ADDR_REGS;
462:
463: case X_OR_Y_ADDR_REGS:
464: return class;
465:
466: case Y_OR_Y_ADDR_REGS:
467: case P_OR_Y_ADDR_REGS:
468: case NON_HIGH_YBASE_ELIGIBLE_REGS:
469:
470: case J_REG:
471: return class;
472:
473: case YBASE_ELIGIBLE_REGS:
474: if (GET_MODE_SIZE(mode) > 1)
475: return ACCUM_Y_P_OR_YBASE_REGS;
476: else
477: return NON_HIGH_YBASE_ELIGIBLE_REGS;
478:
479: case J_OR_DAU_16_BIT_REGS:
480: if (GET_MODE_SIZE(mode) == 1)
481: return J_REG;
482: else
483: return class;
484:
485: case BMU_REGS:
486: case NOHIGH_NON_ADDR_REGS:
487: return class;
488:
489: case NON_ADDR_REGS:
490: if (GET_MODE_SIZE(mode) > 1)
491: return class;
492: else
493: return NOHIGH_NON_ADDR_REGS;
494:
495: case NOHIGH_NON_YBASE_REGS:
496: return class;
497:
498: case NON_YBASE_REGS:
499: if (GET_MODE_SIZE(mode) > 1)
500: return class;
501: else
502: return NOHIGH_NON_YBASE_REGS;
503:
504: case YBASE_VIRT_REGS:
505: case ACCUM_LOW_OR_YBASE_REGS:
506: return class;
507:
508: case ACCUM_OR_YBASE_REGS:
509: if (GET_MODE_SIZE(mode) > 1)
510: return class;
511: else
512: return ACCUM_LOW_OR_YBASE_REGS;
513:
514: case X_OR_YBASE_REGS:
515: return class;
516:
517: case Y_OR_YBASE_REGS:
518: case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
519: case P_OR_YBASE_REGS:
520: return class;
521:
522: case ACCUM_Y_P_OR_YBASE_REGS:
523: return ACCUM_LOW_YL_PL_OR_YBASE_REGS;
524:
525: case Y_ADDR_OR_YBASE_REGS:
526: case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
527: return class;
528:
529: case YBASE_OR_YBASE_ELIGIBLE_REGS:
530: if (GET_MODE_SIZE(mode) > 1)
531: return class;
532: else
533: return YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS;
534:
535: case NO_HIGH_ALL_REGS:
536: return class;
537:
538: case ALL_REGS:
539: if (GET_MODE_SIZE(mode) > 1)
540: return class;
541: else
542: return NO_HIGH_ALL_REGS;
543:
544: default:
545: return class;
546: }
547: }
548:
549: int
550: dsp16xx_register_move_cost (from, to)
551: enum reg_class from, to;
552: {
553: #if 0
554: if (from == NO_REGS || to == NO_REGS || (from == to))
555: return 2;
556: #endif
557:
558: if (from == A0H_REG || from == A0L_REG || from == A0_REG ||
559: from == A1H_REG || from == ACCUM_HIGH_REGS || from == A1L_REG ||
560: from == ACCUM_LOW_REGS || from == A1_REG || from == ACCUM_REGS)
561: {
562: if (to == Y_REG || to == P_REG)
563: return 4;
564: else
565: return 2;
566: }
567:
568: if (to == A0H_REG || to == A0L_REG || to == A0_REG ||
569: to == A1H_REG || to == ACCUM_HIGH_REGS || to == A1L_REG ||
570: to == ACCUM_LOW_REGS || to == A1_REG || to == ACCUM_REGS)
571: {
572: return 2;
573: }
574:
575: #if 0
576: if (from == YBASE_VIRT_REGS)
577: {
578: if (to == X_REG || to == YH_REG || to == YL_REG ||
579: to == Y_REG || to == PL_REG || to == PH_REG ||
580: to == P_REG || to == Y_ADDR_REGS || to == YBASE_ELIGIBLE_REGS ||
581: to == Y_OR_P_REGS)
582: {
583: return 2;
584: }
585: else
586: return 4;
587: }
588:
589: if (to == YBASE_VIRT_REGS)
590: {
591: if (from == X_REG || from == YH_REG || from == YL_REG ||
592: from == Y_REG || from == PL_REG || from == PH_REG ||
593: from == P_REG || from == Y_ADDR_REGS || from == YBASE_ELIGIBLE_REGS ||
594: from == Y_OR_P_REGS)
595: {
596: return 2;
597: }
598: else
599: return 4;
600: }
601: #endif
602: return 4;
603: }
604:
605: /* Given an rtx X being reloaded into a reg required to be
606: in class CLASS, return the class of reg to actually use.
607: In general this is just CLASS; but on some machines
608: in some cases it is preferable to use a more restrictive class.
609: Also, we must ensure that a PLUS is reloaded either
610: into an accumulator or an address register. */
611:
612: enum reg_class
613: preferred_reload_class (x, class)
614: rtx x;
615: enum reg_class class;
616: {
617: /* The ybase registers cannot have constants copied directly
618: to them. */
619:
620: if (CONSTANT_P (x))
621: {
622: if (class == ALL_REGS)
623: return NON_YBASE_REGS;
624: }
625:
626: if (class == ALL_REGS && REG_P (x) && !TARGET_RESERVE_YBASE
627: && IS_YBASE_REGISTER_WINDOW (REGNO(x)))
628: return YBASE_ELIGIBLE_REGS;
629:
630: if (GET_CODE (x) == PLUS)
631: {
632: if (GET_MODE (x) == QImode
633: && REG_P (XEXP (x,0))
634: && (XEXP (x,0) == frame_pointer_rtx
635: || XEXP (x,0) == stack_pointer_rtx)
636: && (GET_CODE (XEXP (x,1)) == CONST_INT))
637: {
638: if (class == ACCUM_HIGH_REGS)
639: return class;
640:
641: if (reg_class_subset_p (ACCUM_HIGH_REGS, class))
642: return ACCUM_HIGH_REGS;
643:
644: /* We will use accumulator 'a1l' for reloading a
645: PLUS. We can only use one accumulator because
646: 'reload_inqi' only allows one alternative to be
647: used. */
648:
649: else if (class == ACCUM_LOW_REGS)
650: return A1L_REG;
651: else if (class == A0L_REG)
652: return NO_REGS;
653: else
654: return class;
655: }
656:
657: if (class == NON_YBASE_REGS || class == YBASE_ELIGIBLE_REGS)
658: return Y_ADDR_REGS;
659: else
660: return class;
661: }
662: else if (GET_CODE (x) == MEM)
663: {
664: if (class == ALL_REGS)
665: {
666: #if 0
667: if (GET_MODE(x) == HImode)
668: return NO_ACCUM_NON_YBASE_REGS;
669: else
670: #endif
671: return NON_YBASE_REGS;
672: }
673: else
674: return class;
675: }
676: else
677: return class;
678: }
679:
680: /* Return the register class of a scratch register needed to copy IN into
681: or out of a register in CLASS in MODE. If it can be done directly,
682: NO_REGS is returned. */
683:
684: enum reg_class
685: secondary_reload_class (class, mode, in)
686: enum reg_class class;
687: enum machine_mode mode;
688: rtx in;
689: {
690: int regno = -1;
691:
692: if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
693: regno = true_regnum (in);
694:
695: if (class == ACCUM_HIGH_REGS
696: || class == ACCUM_LOW_REGS
697: || class == A1L_REG
698: || class == A0L_REG
699: || class == A1H_REG
700: || class == A0H_REG)
701: {
702: if (GET_CODE (in) == PLUS && mode == QImode)
703: {
704: rtx addr0 = XEXP (in, 0);
705: rtx addr1 = XEXP (in, 1);
706:
707: /* If we are reloading a plus (reg:QI) (reg:QI)
708: we need an additional register. */
709: if (REG_P (addr0) && REG_P (addr1))
710: return NO_REGS;
711: }
712: }
713:
714: /* We can place anything into ACCUM_REGS and can put ACCUM_REGS
715: into anything. */
716:
717: if ((class == ACCUM_REGS || class == ACCUM_HIGH_REGS ||
718: class == ACCUM_LOW_REGS || class == A0H_REG || class == A0L_REG ||
719: class == A1H_REG || class == A1_REG) ||
720: (regno >= REG_A0 && regno < REG_A1L + 1))
721: return NO_REGS;
722:
723: /* We can copy the ybase registers into:
724: r0-r3, a0-a1, y, p, & x or the union of
725: any of these. */
726:
727: if (!TARGET_RESERVE_YBASE && IS_YBASE_REGISTER_WINDOW(regno))
728: {
729: switch ((int) class)
730: {
731: case (int) X_REG:
732: case (int) X_OR_ACCUM_LOW_REGS:
733: case (int) X_OR_ACCUM_REGS:
734: case (int) YH_REG:
735: case (int) YH_OR_ACCUM_HIGH_REGS:
736: case (int) X_OR_YH_REGS:
737: case (int) YL_REG:
738: case (int) YL_OR_ACCUM_LOW_REGS:
739: case (int) X_OR_Y_REGS:
740: case (int) X_OR_YL_REGS:
741: case (int) Y_REG:
742: case (int) ACCUM_OR_Y_REGS:
743: case (int) PH_REG:
744: case (int) X_OR_PH_REGS:
745: case (int) PL_REG:
746: case (int) PL_OR_ACCUM_LOW_REGS:
747: case (int) X_OR_PL_REGS:
748: case (int) YL_OR_PL_OR_ACCUM_LOW_REGS:
749: case (int) P_REG:
750: case (int) ACCUM_OR_P_REGS:
751: case (int) YL_OR_P_REGS:
752: case (int) ACCUM_LOW_OR_YL_OR_P_REGS:
753: case (int) Y_OR_P_REGS:
754: case (int) ACCUM_Y_OR_P_REGS:
755: case (int) Y_ADDR_REGS:
756: case (int) ACCUM_LOW_OR_Y_ADDR_REGS:
757: case (int) ACCUM_OR_Y_ADDR_REGS:
758: case (int) X_OR_Y_ADDR_REGS:
759: case (int) Y_OR_Y_ADDR_REGS:
760: case (int) P_OR_Y_ADDR_REGS:
761: case (int) YBASE_ELIGIBLE_REGS:
762: return NO_REGS;
763:
764: default:
765: return ACCUM_HIGH_REGS;
766: }
767: }
768:
769: /* We can copy r0-r3, a0-a1, y, & p
770: directly to the ybase registers. In addition
771: we can use any of the ybase virtual registers
772: as the secondary reload registers when copying
773: between any of these registers. */
774:
775: if (!TARGET_RESERVE_YBASE && regno != -1)
776: {
777: switch (regno)
778: {
779: case REG_A0:
780: case REG_A0L:
781: case REG_A1:
782: case REG_A1L:
783: case REG_X:
784: case REG_Y:
785: case REG_YL:
786: case REG_PROD:
787: case REG_PRODL:
788: case REG_R0:
789: case REG_R1:
790: case REG_R2:
791: case REG_R3:
792: if (class == YBASE_VIRT_REGS)
793: return NO_REGS;
794: else
795: {
796: switch ((int) class)
797: {
798: case (int) X_REG:
799: case (int) X_OR_ACCUM_LOW_REGS:
800: case (int) X_OR_ACCUM_REGS:
801: case (int) YH_REG:
802: case (int) YH_OR_ACCUM_HIGH_REGS:
803: case (int) X_OR_YH_REGS:
804: case (int) YL_REG:
805: case (int) YL_OR_ACCUM_LOW_REGS:
806: case (int) X_OR_Y_REGS:
807: case (int) X_OR_YL_REGS:
808: case (int) Y_REG:
809: case (int) ACCUM_OR_Y_REGS:
810: case (int) PH_REG:
811: case (int) X_OR_PH_REGS:
812: case (int) PL_REG:
813: case (int) PL_OR_ACCUM_LOW_REGS:
814: case (int) X_OR_PL_REGS:
815: case (int) YL_OR_PL_OR_ACCUM_LOW_REGS:
816: case (int) P_REG:
817: case (int) ACCUM_OR_P_REGS:
818: case (int) YL_OR_P_REGS:
819: case (int) ACCUM_LOW_OR_YL_OR_P_REGS:
820: case (int) Y_OR_P_REGS:
821: case (int) ACCUM_Y_OR_P_REGS:
822: case (int) Y_ADDR_REGS:
823: case (int) ACCUM_LOW_OR_Y_ADDR_REGS:
824: case (int) ACCUM_OR_Y_ADDR_REGS:
825: case (int) X_OR_Y_ADDR_REGS:
826: case (int) Y_OR_Y_ADDR_REGS:
827: case (int) P_OR_Y_ADDR_REGS:
828: case (int) YBASE_ELIGIBLE_REGS:
829: return YBASE_VIRT_REGS;
830:
831: default:
832: break;
833: }
834: }
835: }
836: }
837:
838: /* Memory or constants can be moved from or to any register
839: except the ybase virtual registers */
840: if (regno == -1 && GET_CODE(in) != PLUS)
841: {
842: if (class == YBASE_VIRT_REGS)
843: return NON_YBASE_REGS;
844: else
845: return NO_REGS;
846: }
847:
848: if (GET_CODE (in) == PLUS && mode == QImode)
849: {
850: rtx addr0 = XEXP (in, 0);
851: rtx addr1 = XEXP (in, 1);
852:
853: /* If we are reloading a plus (reg:QI) (reg:QI)
854: we need a low accumulator, not a high one. */
855: if (REG_P (addr0) && REG_P (addr1))
856: return ACCUM_LOW_REGS;
857: }
858:
859: #if 0
860: if (REG_P(in))
861: return ACCUM_REGS;
862: #endif
863:
864: /* Otherwise, we need a high accumulator(s). */
865: return ACCUM_HIGH_REGS;
866: }
867:
868: int
869: symbolic_address_operand (op, mode)
870: rtx op;
871: enum machine_mode mode;
872: {
873: return (symbolic_address_p (op));
874:
875: }
876:
877: int symbolic_address_p (op)
878: rtx op;
879: {
880: switch (GET_CODE (op))
881: {
882: case SYMBOL_REF:
883: case LABEL_REF:
884: return 1;
885:
886: case CONST:
887: op = XEXP (op, 0);
888: return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
889: || GET_CODE (XEXP (op, 0)) == LABEL_REF)
890: && GET_CODE (XEXP (op, 1)) == CONST_INT
891: && INTVAL (XEXP (op,1)) < 0x20);
892:
893: default:
894: return 0;
895: }
896: }
897:
898: /* For a Y address space operand we allow only *rn, *rn++, *rn--.
899: This routine only recognizes *rn, the '<>' constraints recognize
900: *rn++, *rn-- */
901:
902: int
903: Y_address_operand (op, mode)
904: rtx op;
905: enum machine_mode mode;
906: {
907: return (memory_address_p (mode, op) && !symbolic_address_p (op));
908: }
909:
910: int
911: sp_operand (op, mode)
912: rtx op;
913: enum machine_mode mode;
914: {
915: return (GET_CODE (op) == PLUS
916: && (XEXP (op, 0) == stack_pointer_rtx
917: || XEXP (op, 0) == frame_pointer_rtx)
918: && GET_CODE (XEXP (op,1)) == CONST_INT);
919: }
920:
921: int
922: sp_operand2 (op, mode)
923: rtx op;
924: enum machine_mode mode;
925: {
926: if ((GET_CODE (op) == PLUS
927: && (XEXP (op, 0) == stack_pointer_rtx
928: || XEXP (op, 0) == frame_pointer_rtx)
929: && (REG_P (XEXP (op,1))
930: && IS_ADDRESS_REGISTER (REGNO (XEXP(op, 1))))))
931: return 1;
932: else if ((GET_CODE (op) == PLUS
933: && (XEXP (op, 1) == stack_pointer_rtx
934: || XEXP (op, 1) == frame_pointer_rtx)
935: && (REG_P (XEXP (op,0))
936: && IS_ADDRESS_REGISTER (REGNO (XEXP(op, 1))))))
937: return 1;
938: else
939: return 0;
940: }
941:
942: int
943: nonmemory_arith_operand (op, mode)
944: rtx op;
945: enum machine_mode mode;
946: {
947: return (immediate_operand (op, mode) || arith_reg_operand (op, mode));
948: }
949:
950: int
951: arith_reg_operand (op, mode)
952: rtx op;
953: enum machine_mode mode;
954: {
955: return (register_operand (op, mode)
956: && (GET_CODE (op) != REG
957: || REGNO (op) >= FIRST_PSEUDO_REGISTER
958: || (!(IS_YBASE_REGISTER_WINDOW (REGNO (op)))
959: && REGNO (op) != FRAME_POINTER_REGNUM)));
960: }
961:
962: int
963: call_address_operand (op, mode)
964: rtx op;
965: enum machine_mode mode;
966: {
967: if (symbolic_address_p (op) || REG_P(op))
968: {
969: return 1;
970: }
971:
972: return 0;
973: }
974:
975: int
976: dsp16xx_comparison_operator (op, mode)
977: register rtx op;
978: enum machine_mode mode;
979: {
980: return ((mode == VOIDmode || GET_MODE (op) == mode)
981: && GET_RTX_CLASS (GET_CODE (op)) == '<'
982: && (GET_CODE(op) != GE && GET_CODE (op) != LT &&
983: GET_CODE (op) != GEU && GET_CODE (op) != LTU));
984: }
985:
986: void
987: notice_update_cc(exp)
988: rtx exp;
989: {
990: if (GET_CODE (exp) == SET)
991: {
992: /* Jumps do not alter the cc's. */
993:
994: if (SET_DEST (exp) == pc_rtx)
995: return;
996:
997: /* Moving register or memory into a register:
998: it doesn't alter the cc's, but it might invalidate
999: the RTX's which we remember the cc's came from.
1000: (Note that moving a constant 0 or 1 MAY set the cc's). */
1001: if (REG_P (SET_DEST (exp))
1002: && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
1003: {
1004: if (cc_status.value1
1005: && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
1006: cc_status.value1 = 0;
1007: if (cc_status.value2
1008: && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
1009: cc_status.value2 = 0;
1010: return;
1011: }
1012: /* Moving register into memory doesn't alter the cc's.
1013: It may invalidate the RTX's which we remember the cc's came from. */
1014: if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
1015: {
1016: if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM)
1017: cc_status.value1 = 0;
1018: if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM)
1019: cc_status.value2 = 0;
1020: return;
1021: }
1022: /* Function calls clobber the cc's. */
1023: else if (GET_CODE (SET_SRC (exp)) == CALL)
1024: {
1025: CC_STATUS_INIT;
1026: return;
1027: }
1028: /* Tests and compares set the cc's in predictable ways. */
1029: else if (SET_DEST (exp) == cc0_rtx)
1030: {
1031: CC_STATUS_INIT;
1032: cc_status.value1 = SET_SRC (exp);
1033: return;
1034: }
1035: /* Certain instructions effect the condition codes. */
1036: else if (GET_MODE_CLASS (GET_MODE (SET_SRC (exp))) == MODE_INT)
1037: switch( GET_CODE (SET_SRC (exp)) )
1038: {
1039: case PLUS:
1040: case MINUS:
1041: if (REG_P (SET_DEST (exp)))
1042: {
1043: /* Address registers don't set the condition codes */
1044: if (IS_ADDRESS_REGISTER (REGNO (SET_DEST (exp))))
1045: {
1046: CC_STATUS_INIT;
1047: break;
1048: }
1049: }
1050: case ASHIFTRT:
1051: case LSHIFTRT:
1052: case ASHIFT:
1053: case AND:
1054: case IOR:
1055: case XOR:
1056: case MULT:
1057: case NEG:
1058: case NOT:
1059: cc_status.value1 = SET_SRC (exp);
1060: cc_status.value2 = SET_DEST (exp);
1061: break;
1062:
1063: default:
1064: CC_STATUS_INIT;
1065: }
1066: else
1067: {
1068: CC_STATUS_INIT;
1069: }
1070: }
1071: else if (GET_CODE (exp) == PARALLEL
1072: && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
1073: {
1074: if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
1075: return;
1076:
1077: if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
1078: {
1079: CC_STATUS_INIT;
1080: cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
1081: return;
1082: }
1083:
1084: CC_STATUS_INIT;
1085: }
1086: else
1087: {
1088: CC_STATUS_INIT;
1089: }
1090: }
1091:
1092: int
1093: dsp16xx_makes_calls ()
1094: {
1095: rtx insn;
1096:
1097: for (insn = get_insns (); insn; insn = next_insn (insn))
1098: if (GET_CODE (insn) == CALL_INSN)
1099: return (1);
1100:
1101: return 0;
1102: }
1103:
1104: long compute_frame_size (size)
1105: int size;
1106: {
1107: long total_size;
1108: long var_size;
1109: long args_size;
1110: long extra_size;
1111: long reg_size;
1112:
1113: reg_size = 0;
1114: extra_size = 0;
1115: var_size = size;
1116: args_size = current_function_outgoing_args_size;
1117: reg_size = reg_save_size ();
1118:
1119: total_size = var_size + args_size + extra_size + reg_size;
1120:
1121:
1122: /* Save other computed information. */
1123: current_frame_info.total_size = total_size;
1124: current_frame_info.var_size = var_size;
1125: current_frame_info.args_size = args_size;
1126: current_frame_info.extra_size = extra_size;
1127: current_frame_info.reg_size = reg_size;
1128: current_frame_info.initialized = reload_completed;
1129: current_frame_info.reg_size = reg_size / UNITS_PER_WORD;
1130: current_frame_info.function_makes_calls = dsp16xx_makes_calls ();
1131:
1132: if (reg_size)
1133: {
1134: unsigned long offset = args_size + var_size + reg_size;
1135: current_frame_info.sp_save_offset = offset;
1136: current_frame_info.fp_save_offset = offset - total_size;
1137: }
1138:
1139: return total_size;
1140: }
1141:
1142: int
1143: dsp16xx_call_saved_register (regno)
1144: int regno;
1145: {
1146: return (regs_ever_live[regno] && !call_used_regs[regno] &&
1147: !IS_YBASE_REGISTER_WINDOW(regno));
1148:
1149: }
1150:
1151: int
1152: ybase_regs_ever_used ()
1153: {
1154: int regno;
1155: int live = 0;
1156:
1157: for (regno = REG_YBASE0; regno <= REG_YBASE31; regno++)
1158: if (regs_ever_live[regno])
1159: {
1160: live = 1;
1161: break;
1162: }
1163:
1164: return live;
1165: }
1166:
1167: void
1168: function_prologue (file, size)
1169: FILE *file;
1170: int size;
1171: {
1172: int regno;
1173: long total_size;
1174: fp = reg_names[FRAME_POINTER_REGNUM];
1175: sp = reg_names[STACK_POINTER_REGNUM];
1176: rr = reg_names[RETURN_ADDRESS_REGNUM]; /* return address register */
1177: a1h = reg_names[REG_A1];
1178:
1179: total_size = compute_frame_size (size);
1180:
1181: fprintf( file, "\t/* FUNCTION PROLOGUE: */\n" );
1182: fprintf (file, "\t/* total=%d, vars= %d, regs= %d, args=%d, extra= %d */\n",
1183: current_frame_info.total_size,
1184: current_frame_info.var_size,
1185: current_frame_info.reg_size,
1186: current_function_outgoing_args_size,
1187: current_frame_info.extra_size);
1188:
1189: fprintf (file, "\t/* fp save offset= %d, sp save_offset= %d */\n\n",
1190: current_frame_info.fp_save_offset,
1191: current_frame_info.sp_save_offset);
1192: /* Set up the 'ybase' register window. */
1193:
1194: if (ybase_regs_ever_used())
1195: {
1196: fprintf (file, "\t%s=%s\n", a1h, reg_names[REG_YBASE]);
1197: if (TARGET_YBASE_HIGH)
1198: fprintf (file, "\t%s=%sh-32\n", reg_names[REG_A1], a1h);
1199: else
1200: fprintf (file, "\t%s=%sh+32\n", reg_names[REG_A1], a1h);
1201: fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h);
1202: }
1203:
1204: #if 0
1205: if (current_frame_info.function_makes_calls)
1206: fprintf( file, "\t*%s++=%s\n", sp, rr ); /* Push return address */
1207: #endif
1208:
1209:
1210: if (current_frame_info.var_size)
1211: {
1212: if (current_frame_info.var_size == 1)
1213: fprintf (file, "\t*%s++\n", sp);
1214: else
1215: {
1216: if(SMALL_INTVAL(current_frame_info.var_size) && ((current_frame_info.var_size & 0x8000) == 0))
1217: fprintf (file, "\t%s=%d\n\t*%s++%s\n", reg_names[REG_J], current_frame_info.var_size, sp, reg_names[REG_J]);
1218: else
1219: fatal ("Stack size > 32k");
1220: }
1221: }
1222:
1223: /* Save any registers this function uses, unless they are
1224: * used in a call, in which case we don't need to
1225: */
1226:
1227: for( regno = 0; regno < FIRST_PSEUDO_REGISTER; ++ regno )
1228: if (dsp16xx_call_saved_register (regno))
1229: {
1230: #if OLD_REGISTER_SAVE
1231: fprintf( file, "\t*%s++=%s\n", sp, reg_names[regno] );
1232: #else
1233: fprintf( file, "\tpush(*%s)=%s\n", sp, reg_names[regno] );
1234: #endif
1235: }
1236:
1237: if (current_frame_info.args_size)
1238: {
1239: if (current_frame_info.args_size == 1)
1240: fprintf (file, "\t*%s++\n", sp);
1241: else
1242: {
1243: if(SMALL_INTVAL(current_frame_info.args_size) && ((current_frame_info.args_size & 0x8000) == 0))
1244: fprintf (file, "\t%s=%d\n\t*%s++%s\n", reg_names[REG_J], current_frame_info.args_size, sp, reg_names[REG_J]);
1245: else
1246: fatal ("Stack size > 32k");
1247: }
1248: }
1249:
1250: if (frame_pointer_needed)
1251: {
1252: fprintf( file, "\t%s=%s\n", a1h, sp );
1253: fprintf( file, "\t%s=%s\n", fp, a1h ); /* Establish new base frame */
1254: fprintf( file, "\t%s=%d\n", reg_names[REG_J], -total_size);
1255: fprintf( file, "\t*%s++%s\n", fp, reg_names[REG_J]);
1256: }
1257:
1258: fprintf( file, "\t/* END FUNCTION PROLOGUE: */\n\n" );
1259: }
1260:
1261: void
1262: init_emulation_routines ()
1263: {
1264: dsp16xx_addhf3_libcall = (rtx) 0;
1265: dsp16xx_subhf3_libcall = (rtx) 0;
1266: dsp16xx_mulhf3_libcall = (rtx) 0;
1267: dsp16xx_divhf3_libcall = (rtx) 0;
1268: dsp16xx_cmphf3_libcall = (rtx) 0;
1269: dsp16xx_fixhfhi2_libcall = (rtx) 0;
1270: dsp16xx_floathihf2_libcall = (rtx) 0;
1271: dsp16xx_neghf2_libcall = (rtx) 0;
1272:
1273: dsp16xx_mulhi3_libcall = (rtx) 0;
1274: dsp16xx_udivqi3_libcall = (rtx) 0;
1275: dsp16xx_udivhi3_libcall = (rtx) 0;
1276: dsp16xx_divqi3_libcall = (rtx) 0;
1277: dsp16xx_divhi3_libcall = (rtx) 0;
1278: dsp16xx_modqi3_libcall = (rtx) 0;
1279: dsp16xx_modhi3_libcall = (rtx) 0;
1280: dsp16xx_umodqi3_libcall = (rtx) 0;
1281: dsp16xx_umodhi3_libcall = (rtx) 0;
1282: dsp16xx_ashrhi3_libcall = (rtx) 0;
1283: dsp16xx_ashlhi3_libcall = (rtx) 0;
1284: dsp16xx_ucmphi2_libcall = (rtx) 0;
1285: dsp16xx_lshrhi3_libcall = (rtx) 0;
1286:
1287: }
1288: void
1289: function_epilogue (file, size)
1290: FILE *file;
1291: int size;
1292: {
1293: int regno;
1294: int initial_stack_dec = 0;
1295:
1296: fp = reg_names[FRAME_POINTER_REGNUM];
1297: sp = reg_names[STACK_POINTER_REGNUM];
1298: rr = reg_names[RETURN_ADDRESS_REGNUM]; /* return address register */
1299: a1h = reg_names[REG_A1];
1300:
1301: fprintf( file, "\n\t/* FUNCTION EPILOGUE: */\n" );
1302:
1303: if (current_frame_info.args_size)
1304: {
1305: if (current_frame_info.args_size == 1)
1306: fprintf (file, "\t*%s--\n", sp);
1307: else
1308: {
1309: fprintf (file, "\t%s=%d\n\t*%s++%s\n",
1310: reg_names[REG_J], -current_frame_info.args_size, sp, reg_names[REG_J]);
1311: }
1312: }
1313:
1314: if (ybase_regs_ever_used())
1315: {
1316: fprintf (file, "\t%s=%s\n", a1h, reg_names[REG_YBASE]);
1317: if (TARGET_YBASE_HIGH)
1318: fprintf (file, "\t%s=%sh+32\n", reg_names[REG_A1], a1h);
1319: else
1320: fprintf (file, "\t%s=%sh-32\n", reg_names[REG_A1], a1h);
1321: fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h);
1322: }
1323:
1324: for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)
1325: if (dsp16xx_call_saved_register(regno))
1326: {
1327: #if OLD_REGISTER_SAVE
1328: if (!initial_stack_dec)
1329: {
1330: initial_stack_dec = 1;
1331: fprintf (file, "\t*%s--\n", sp);
1332: }
1333: #endif
1334:
1335: #if OLD_REGISTER_SAVE
1336: fprintf( file, "\t%s=*%s--\n", reg_names[regno], sp );
1337: #else
1338: fprintf( file, "\t%s=pop(*%s)\n", reg_names[regno], sp );
1339: #endif
1340: }
1341:
1342: /* If we restored any registers we have to account for the
1343: initial pre-decrement. But only if we had any local variables
1344: or spills. */
1345: #if OLD_REGISTER_SAVE
1346: if (initial_stack_dec)
1347: fprintf (file, "\t*%s++\n", sp);
1348: #endif
1349:
1350: if (current_frame_info.var_size)
1351: {
1352: if (current_frame_info.var_size == 1)
1353: fprintf (file, "\t*%s--\n", sp);
1354: else
1355: {
1356: fprintf (file, "\t%s=%d\n\t*%s++%s\n",
1357: reg_names[REG_J], -current_frame_info.var_size, sp, reg_names[REG_J]);
1358: }
1359: }
1360:
1361: fprintf (file, "\treturn\n");
1362: /* Reset the frame info for the next function */
1363: current_frame_info = zero_frame_info;
1364: init_emulation_routines ();
1365: }
1366:
1367: /* Emit insns to move operands[1] into operands[0].
1368:
1369: Return 1 if we have written out everything that needs to be done to
1370: do the move. Otherwise, return 0 and the caller will emit the move
1371: normally. */
1372:
1373: int
1374: emit_move_sequence (operands, mode)
1375: rtx *operands;
1376: enum machine_mode mode;
1377: {
1378: register rtx operand0 = operands[0];
1379: register rtx operand1 = operands[1];
1380:
1381: /* We can only store registers to memory. */
1382:
1383: if (GET_CODE (operand0) == MEM && GET_CODE (operand1) != REG)
1384: operands[1] = force_reg (mode, operand1);
1385:
1386: return 0;
1387: }
1388:
1389: void
1390: double_reg_from_memory (operands)
1391: rtx operands[];
1392: {
1393: rtx xoperands[4];
1394:
1395: if (GET_CODE(XEXP(operands[1],0)) == POST_INC)
1396: {
1397: output_asm_insn ("%u0=%1", operands);
1398: output_asm_insn ("%w0=%1", operands);
1399: }
1400: else if (GET_CODE(XEXP(operands[1],0)) == POST_DEC)
1401: {
1402: xoperands[1] = XEXP (XEXP (operands[1], 0), 0);
1403: xoperands[0] = operands[0];
1404:
1405: /* We can't use j anymore since the compiler can allocate it. */
1406: /* output_asm_insn ("j=-3\n\t%u0=*%1++\n\t%w0=*%1++j", xoperands); */
1407: output_asm_insn ("%u0=*%1++\n\t%w0=*%1--\n\t*%1--\n\t*%1--", xoperands);
1408: }
1409: else if (GET_CODE(XEXP(operands[1],0)) == PLUS)
1410: {
1411: rtx addr;
1412: rtx base;
1413: int offset;
1414:
1415: output_asm_insn ("%u0=%1", operands);
1416:
1417:
1418: /* In order to print out the least significant word we must
1419: use 'offset + 1'. */
1420: addr = XEXP (operands[1], 0);
1421: if (GET_CODE (XEXP(addr,0)) == CONST_INT)
1422: offset = INTVAL(XEXP(addr,0)) + 1;
1423: else if (GET_CODE (XEXP(addr,1)) == CONST_INT)
1424: offset = INTVAL(XEXP(addr,1)) + 1;
1425:
1426: fprintf (asm_out_file, "\t%s=*(%d)\n", reg_names[REGNO(operands[0]) + 1], offset + 31);
1427: }
1428: else
1429: {
1430: xoperands[1] = XEXP(operands[1],0);
1431: xoperands[0] = operands[0];
1432:
1433: output_asm_insn ("%u0=*%1++\n\t%w0=*%1--", xoperands);
1434: }
1435: }
1436:
1437:
1438: void
1439: double_reg_to_memory (operands)
1440: rtx operands[];
1441: {
1442: rtx xoperands[4];
1443:
1444: if (GET_CODE(XEXP(operands[0],0)) == POST_INC)
1445: {
1446: output_asm_insn ("%0=%u1", operands);
1447: output_asm_insn ("%0=%w1", operands);
1448: }
1449: else if (GET_CODE(XEXP(operands[0],0)) == POST_DEC)
1450: {
1451: xoperands[0] = XEXP (XEXP (operands[0], 0), 0);
1452: xoperands[1] = operands[1];
1453:
1454: /* We can't use j anymore since the compiler can allocate it. */
1455:
1456: /* output_asm_insn ("j=-3\n\t*%0++=%u1\n\t*%0++j=%w1", xoperands); */
1457: output_asm_insn ("*%0++=%u1\n\t*%0--=%w1\n\t*%0--\n\t*%0--", xoperands);
1458:
1459: }
1460: else if (GET_CODE(XEXP(operands[0],0)) == PLUS)
1461: {
1462: rtx addr;
1463: int offset;
1464:
1465: output_asm_insn ("%0=%u1", operands);
1466:
1467: /* In order to print out the least significant word we must
1468: use 'offset + 1'. */
1469: addr = XEXP (operands[0], 0);
1470: if (GET_CODE (XEXP(addr,0)) == CONST_INT)
1471: offset = INTVAL(XEXP(addr,0)) + 1;
1472: else if (GET_CODE (XEXP(addr,1)) == CONST_INT)
1473: offset = INTVAL(XEXP(addr,1)) + 1;
1474: else
1475: fatal ("Illegal addressing mode");
1476:
1477: fprintf (asm_out_file, "\t*(%d)=%s\n", offset + 31, reg_names[REGNO(operands[1]) + 1]);
1478: }
1479: else
1480: {
1481: xoperands[0] = XEXP(operands[0],0);
1482: xoperands[1] = operands[1];
1483:
1484: output_asm_insn ("*%0++=%u1\n\t*%0--=%w1", xoperands);
1485: }
1486: }
1487:
1488: void
1489: override_options ()
1490: {
1491: if (chip_name == (char *) 0)
1492: chip_name = DEFAULT_CHIP_NAME;
1493:
1494: if (text_seg_name == (char *) 0)
1495: text_seg_name = DEFAULT_TEXT_SEG_NAME;
1496:
1497: if (data_seg_name == (char *) 0)
1498: data_seg_name = DEFAULT_DATA_SEG_NAME;
1499:
1500: if (bss_seg_name == (char *) 0)
1501: bss_seg_name = DEFAULT_BSS_SEG_NAME;
1502:
1503: if (const_seg_name == (char *) 0)
1504: const_seg_name = DEFAULT_CONST_SEG_NAME;
1505:
1506: save_chip_name = (char *) xmalloc (strlen(chip_name) + 1);
1507: strcpy (save_chip_name, chip_name);
1508:
1509: rsect_text = (char *) xmalloc (strlen(".rsect ") +
1510: strlen(text_seg_name) + 3);
1511: rsect_data = (char *) xmalloc (strlen(".rsect ") +
1512: strlen(data_seg_name) + 3);
1513: rsect_bss = (char *) xmalloc (strlen(".rsect ") +
1514: strlen(bss_seg_name) + 3);
1515: rsect_const = (char *) xmalloc (strlen(".rsect ") +
1516: strlen(const_seg_name) + 3);
1517:
1518: sprintf (rsect_text, ".rsect \"%s\"", text_seg_name);
1519: sprintf (rsect_data, ".rsect \"%s\"", data_seg_name);
1520: sprintf (rsect_bss, ".rsect \"%s\"", bss_seg_name);
1521: sprintf (rsect_const, ".rsect \"%s\"", const_seg_name);
1522:
1523: if (optimize)
1524: {
1525: if (TARGET_OPTIMIZE_SPEED)
1526: {
1527: flag_unroll_loops = 1;
1528: flag_inline_functions = 1;
1529: }
1530: }
1531: }
1532:
1533: enum rtx_code save_next_cc_user_code;
1534:
1535: enum rtx_code
1536: next_cc_user_code (insn)
1537: rtx insn;
1538: {
1539: if ( !(insn = next_cc0_user (insn)))
1540: abort ();
1541: else if (GET_CODE (insn) == JUMP_INSN
1542: && GET_CODE (PATTERN (insn)) == SET
1543: && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
1544: return GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0));
1545: else if (GET_CODE (insn) == INSN
1546: && GET_CODE (PATTERN (insn)) == SET
1547: && comparison_operator (SET_SRC (PATTERN (insn)), VOIDmode))
1548: return GET_CODE (SET_SRC (PATTERN (insn)));
1549: else
1550: abort ();
1551: }
1552:
1553: void
1554: print_operand(file, op, letter)
1555: FILE *file;
1556: rtx op;
1557: int letter;
1558: {
1559: enum rtx_code code;
1560:
1561: code = GET_CODE(op);
1562:
1563: switch (letter)
1564: {
1565: case 'I':
1566: code = reverse_condition (code);
1567: /* Fallthrough */
1568:
1569: case 'C':
1570: if (code == EQ)
1571: {
1572: fputs ("eq", file);
1573: return;
1574: }
1575: else if (code == NE)
1576: {
1577: fputs ("ne", file);
1578: return;
1579: }
1580: else if (code == GT || code == GTU)
1581: {
1582: fputs ("gt", file);
1583: return;
1584: }
1585: else if (code == LT || code == LTU)
1586: {
1587: fputs ("mi", file);
1588: return;
1589: }
1590: else if (code == GE || code == GEU)
1591: {
1592: fputs ("pl", file);
1593: return;
1594: }
1595: else if (code == LE || code == LEU)
1596: {
1597: fputs ("le", file);
1598: return;
1599: }
1600: else
1601: abort ();
1602: break;
1603:
1604: default:
1605: break;
1606: }
1607:
1608: if( code == REG )
1609: {
1610: /* Print the low half of a 32-bit register pair */
1611: if (letter == 'w')
1612: fprintf( file, "%s", reg_names[REGNO(op)+1] );
1613: else if (letter == 'u' || !letter)
1614: fprintf( file, "%s", reg_names[REGNO(op)]);
1615: else if (letter == 'b')
1616: fprintf ( file, "%sh", reg_names[REGNO(op)]);
1617: else if (letter == 'm')
1618: fprintf (file, "%s", himode_reg_name[REGNO(op)]);
1619: else
1620: fatal("Bad register extension code");
1621: }
1622: else if( code == MEM )
1623: output_address( XEXP(op,0) );
1624: else if( code == CONST_INT )
1625: {
1626: if( letter == 'H' )
1627: fprintf( file, "0x%x", (INTVAL(op) & 0xffff) );
1628: else if (letter == 'h')
1629: fprintf( file, "%d", INTVAL (op) );
1630: else if( letter == 'U' )
1631: fprintf( file, "0x%x", ((INTVAL(op) & 0xffff0000) >> 16) & 0xffff );
1632: else
1633: output_addr_const( file, op );
1634: }
1635: else if( code == CONST_DOUBLE && GET_MODE(op) != DImode )
1636: {
1637: union { double d; int i[2]; } u;
1638: union { float f; int i; } u1;
1639: u.i[0] = CONST_DOUBLE_LOW (op);
1640: u.i[1] = CONST_DOUBLE_HIGH (op);
1641: u1.f = u.d;
1642: fprintf( file, "0x%x", u1.i );
1643: }
1644: else output_addr_const( file, op);
1645: }
1646:
1647:
1648: void
1649: print_operand_address(file, addr)
1650: FILE *file;
1651: rtx addr;
1652: {
1653: rtx base;
1654: int offset;
1655:
1656: switch (GET_CODE (addr))
1657: {
1658: case REG:
1659: fprintf (file, "*%s", reg_names[REGNO (addr)]);
1660: break;
1661: case POST_DEC:
1662: fprintf (file, "*%s--", reg_names[REGNO (XEXP (addr, 0))]);
1663: break;
1664: case POST_INC:
1665: fprintf (file, "*%s++", reg_names[REGNO (XEXP (addr, 0))]);
1666: break;
1667: case PLUS:
1668: if (GET_CODE (XEXP(addr,0)) == CONST_INT)
1669: offset = INTVAL(XEXP(addr,0)), base = XEXP(addr,1);
1670: else if (GET_CODE (XEXP(addr,1)) == CONST_INT)
1671: offset = INTVAL(XEXP(addr,1)), base = XEXP(addr,0);
1672: if (GET_CODE (base) == REG && REGNO(base) == STACK_POINTER_REGNUM)
1673: {
1674: if (offset >= -31 && offset <= 0)
1675: offset = 31 + offset;
1676: else
1677: fatal ("Illegal offset in ybase addressing");
1678: }
1679: else
1680: fatal ("Illegal register in ybase addresing");
1681:
1682: fprintf (file, "*(%d)", offset);
1683: break;
1684:
1685: default:
1686: if( FITS_5_BITS( addr ) )
1687: fprintf( file, "*(0x%x)", (INTVAL(addr) & 0x20) );
1688: else
1689: output_addr_const(file, addr);
1690: }
1691: }
1692:
1693: void
1694: output_dsp16xx_float_const(operands)
1695: rtx *operands;
1696: {
1697: rtx dst = operands[0];
1698: rtx src = operands[1];
1699:
1700: #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
1701: REAL_VALUE_TYPE d;
1702: long value;
1703:
1704: REAL_VALUE_FROM_CONST_DOUBLE (d, src);
1705: REAL_VALUE_TO_TARGET_SINGLE (d, value);
1706:
1707: operands[1] = gen_rtx (CONST_INT, VOIDmode, value);
1708: output_asm_insn ("%u0=%U1\n\t%w0=%H1", operands);
1709: #else
1710: fatal ("inline float constants not supported on this host");
1711: #endif
1712: }
1713:
1714: int
1715: reg_save_size ()
1716: {
1717: int reg_save_size = 0;
1718: int regno;
1719:
1720: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1721: if (dsp16xx_call_saved_register (regno))
1722: {
1723: reg_save_size += UNITS_PER_WORD;
1724: }
1725:
1726: return (reg_save_size);
1727: }
1728:
1729: int
1730: dsp16xx_starting_frame_offset()
1731: {
1732: int reg_save_size = 0;
1733: int regno;
1734:
1735: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1736: if (dsp16xx_call_saved_register (regno))
1737: {
1738: reg_save_size += UNITS_PER_WORD;
1739: }
1740:
1741: return (reg_save_size);
1742: }
1743:
1744: int
1745: initial_frame_pointer_offset()
1746: {
1747: int frame_size;
1748: int regno;
1749: int offset = 0;
1750:
1751: offset = compute_frame_size (get_frame_size());
1752:
1753: #ifdef STACK_GROWS_DOWNWARD
1754: return (offset);
1755: #else
1756: return (-offset);
1757: #endif
1758: }
1759:
1760: /* Generate the minimum number of 1600 core shift instructions
1761: to shift by 'shift_amount'. */
1762:
1763: #if 0
1764: void
1765: emit_1600_core_shift (shift_op, operands, shift_amount, mode)
1766: enum rtx_code shift_op;
1767: rtx *operands;
1768: int shift_amount;
1769: enum machine_mode mode;
1770: {
1771: int quotient;
1772: int i;
1773: int first_shift_emitted = 0;
1774:
1775: while (shift_amount != 0)
1776: {
1777: if (shift_amount/16)
1778: {
1779: quotient = shift_amount/16;
1780: shift_amount = shift_amount - (quotient * 16);
1781: for (i = 0; i < quotient; i++)
1782: emit_insn (gen_rtx (SET, VOIDmode, operands[0],
1783: gen_rtx (shift_op, mode,
1784: first_shift_emitted ? operands[0] : operands[1],
1785: gen_rtx (CONST_INT, VOIDmode, 16))));
1786: first_shift_emitted = 1;
1787: }
1788: else if (shift_amount/8)
1789: {
1790: quotient = shift_amount/8;
1791: shift_amount = shift_amount - (quotient * 8);
1792: for (i = 0; i < quotient; i++)
1793: emit_insn (gen_rtx (SET, VOIDmode, operands[0],
1794: gen_rtx (shift_op, mode,
1795: first_shift_emitted ? operands[0] : operands[1],
1796: gen_rtx (CONST_INT, VOIDmode, 8))));
1797: first_shift_emitted = 1;
1798: }
1799: else if (shift_amount/4)
1800: {
1801: quotient = shift_amount/4;
1802: shift_amount = shift_amount - (quotient * 4);
1803: for (i = 0; i < quotient; i++)
1804: emit_insn (gen_rtx (SET, VOIDmode, operands[0],
1805: gen_rtx (shift_op, mode,
1806: first_shift_emitted ? operands[0] : operands[1],
1807: gen_rtx (CONST_INT, VOIDmode, 4))));
1808: first_shift_emitted = 1;
1809: }
1810: else if (shift_amount/1)
1811: {
1812: quotient = shift_amount/1;
1813: shift_amount = shift_amount - (quotient * 1);
1814: for (i = 0; i < quotient; i++)
1815: emit_insn (gen_rtx (SET, VOIDmode, operands[0],
1816: gen_rtx (shift_op, mode,
1817: first_shift_emitted ? operands[0] : operands[1],
1818: gen_rtx (CONST_INT, VOIDmode, 1))));
1819: first_shift_emitted = 1;
1820: }
1821: }
1822: }
1823: #else
1824: void
1825: emit_1600_core_shift (shift_op, operands, shift_amount)
1826: enum rtx_code shift_op;
1827: rtx *operands;
1828: int shift_amount;
1829: {
1830: int quotient;
1831: int i;
1832: int first_shift_emitted = 0;
1833: char **shift_asm_ptr;
1834: char **shift_asm_ptr_first;
1835:
1836: if (shift_op == ASHIFT)
1837: {
1838: shift_asm_ptr = ashift_left_asm;
1839: shift_asm_ptr_first = ashift_left_asm_first;
1840: }
1841: else if (shift_op == ASHIFTRT)
1842: {
1843: shift_asm_ptr = ashift_right_asm;
1844: shift_asm_ptr_first = ashift_right_asm_first;
1845: }
1846: else if (shift_op == LSHIFTRT)
1847: {
1848: shift_asm_ptr = lshift_right_asm;
1849: shift_asm_ptr_first = lshift_right_asm_first;
1850: }
1851: else
1852: fatal ("Illegal shift operator in emit_1600_core_shift");
1853:
1854: while (shift_amount != 0)
1855: {
1856: if (shift_amount/16)
1857: {
1858: quotient = shift_amount/16;
1859: shift_amount = shift_amount - (quotient * 16);
1860: for (i = 0; i < quotient; i++)
1861: output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_16]
1862: : shift_asm_ptr_first[SHIFT_INDEX_16]), operands);
1863: first_shift_emitted = 1;
1864: }
1865: else if (shift_amount/8)
1866: {
1867: quotient = shift_amount/8;
1868: shift_amount = shift_amount - (quotient * 8);
1869: for (i = 0; i < quotient; i++)
1870: output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_8]
1871: : shift_asm_ptr_first[SHIFT_INDEX_8]), operands);
1872: first_shift_emitted = 1;
1873: }
1874: else if (shift_amount/4)
1875: {
1876: quotient = shift_amount/4;
1877: shift_amount = shift_amount - (quotient * 4);
1878: for (i = 0; i < quotient; i++)
1879: output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_4]
1880: : shift_asm_ptr_first[SHIFT_INDEX_4]), operands);
1881: first_shift_emitted = 1;
1882: }
1883: else if (shift_amount/1)
1884: {
1885: quotient = shift_amount/1;
1886: shift_amount = shift_amount - (quotient * 1);
1887: for (i = 0; i < quotient; i++)
1888: output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_1]
1889: : shift_asm_ptr_first[SHIFT_INDEX_1]), operands);
1890: first_shift_emitted = 1;
1891: }
1892: }
1893: }
1894: #endif
1895: void
1896: asm_output_common(file, name, size, rounded)
1897: FILE *file;
1898: char *name;
1899: int size;
1900: int rounded;
1901: {
1902: bss_section ();
1903: ASM_GLOBALIZE_LABEL (file, name);
1904: assemble_name (file, name);
1905: fputs (":", file);
1906: if (rounded > 1)
1907: fprintf (file, "%d * int\n", rounded);
1908: else
1909: fprintf (file, "int\n");
1910: }
1911:
1912: void
1913: asm_output_local(file, name, size, rounded)
1914: FILE *file;
1915: char *name;
1916: int size;
1917: int rounded;
1918: {
1919: bss_section ();
1920: assemble_name (file, name);
1921: fputs (":", file);
1922: if (rounded > 1)
1923: fprintf (file, "%d * int\n", rounded);
1924: else
1925: fprintf (file, "int\n");
1926: }
1927:
1928: void
1929: asm_output_float (file, fp_const)
1930: FILE *file;
1931: double fp_const;
1932: {
1933: #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
1934: REAL_VALUE_TYPE d = fp_const;
1935: long value;
1936:
1937: REAL_VALUE_TO_TARGET_SINGLE (d, value);
1938: fputs ("\tint ", file);
1939: #ifdef WORDS_BIG_ENDIAN
1940: fprintf (file, "0x%-4.4x, 0x%-4.4x", (value >> 16) & 0xffff, (value & 0xffff));
1941: #else
1942: fprintf (file, "0x%-4.4x, 0x%-4.4x", (value & 0xffff), (value >> 16) & 0xffff);
1943: #endif
1944: fputs ("\n", file);
1945: #else
1946: fatal ("inline float constants not supported on this host");
1947: #endif
1948: }
1949:
1950: void
1951: asm_output_long (file, value)
1952: FILE *file;
1953: long value;
1954: {
1955: fputs ("\tint ", file);
1956: #ifdef WORDS_BIG_ENDIAN
1957: fprintf (file, "0x%-4.4x, 0x%-4.4x", (value >> 16) & 0xffff, (value & 0xffff));
1958: #else
1959: fprintf (file, "0x%-4.4x, 0x%-4.4x", (value & 0xffff), (value >> 16) & 0xffff);
1960: #endif
1961: fputs ("\n", file);
1962: }
1963:
1964: int
1965: dsp16xx_address_cost (addr)
1966: rtx addr;
1967: {
1968: switch (GET_CODE (addr))
1969: {
1970: default:
1971: break;
1972:
1973: case REG:
1974: return 1;
1975:
1976: case CONST:
1977: {
1978: rtx offset = const0_rtx;
1979: addr = eliminate_constant_term (addr, &offset);
1980:
1981: if (GET_CODE (addr) == LABEL_REF)
1982: return 2;
1983:
1984: if (GET_CODE (addr) != SYMBOL_REF)
1985: return 4;
1986:
1987: if (INTVAL (offset) == 0)
1988: return 2;
1989: }
1990: /* fall through */
1991:
1992: case POST_INC: case POST_DEC:
1993: return (GET_MODE (addr) == QImode ? 1 : 2);
1994:
1995: case SYMBOL_REF: case LABEL_REF:
1996: return 2;
1997:
1998: case PLUS:
1999: {
2000: register rtx plus0 = XEXP (addr, 0);
2001: register rtx plus1 = XEXP (addr, 1);
2002:
2003: if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)
2004: {
2005: plus0 = XEXP (addr, 1);
2006: plus1 = XEXP (addr, 0);
2007: }
2008:
2009: if (GET_CODE (plus0) != REG)
2010: break;
2011:
2012: switch (GET_CODE (plus1))
2013: {
2014: default:
2015: break;
2016:
2017: case CONST_INT:
2018: return 4;
2019:
2020: case CONST:
2021: case SYMBOL_REF:
2022: case LABEL_REF:
2023: return dsp16xx_address_cost (plus1) + 1;
2024: }
2025: }
2026: }
2027:
2028: return 4;
2029: }
2030:
2031:
2032: /* Determine whether a function argument is passed in a register, and
2033: which register.
2034:
2035: The arguments are CUM, which summarizes all the previous
2036: arguments; MODE, the machine mode of the argument; TYPE,
2037: the data type of the argument as a tree node or 0 if that is not known
2038: (which happens for C support library functions); and NAMED,
2039: which is 1 for an ordinary argument and 0 for nameless arguments that
2040: correspond to `...' in the called function's prototype.
2041:
2042: The value of the expression should either be a `reg' RTX for the
2043: hard register in which to pass the argument, or zero to pass the
2044: argument on the stack.
2045:
2046: On the dsp1610 the first four words of args are normally in registers
2047: and the rest are pushed. If we a long or on float mode, the argument
2048: must begin on a even register boundary
2049:
2050: Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2051: For structures that are passed in memory, but could have been
2052: passed in registers, we first load the structure into the
2053: register, and then when the last argument is passed, we store
2054: the registers into the stack locations. This fixes some bugs
2055: where GCC did not expect to have register arguments, followed */
2056:
2057:
2058: struct rtx_def *
2059: dsp16xx_function_arg (args_so_far, mode, type, named)
2060: CUMULATIVE_ARGS args_so_far;
2061: enum machine_mode mode;
2062: tree type;
2063: int named;
2064: {
2065: if (TARGET_REGPARM)
2066: {
2067: if ((args_so_far & 1) != 0
2068: && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT))
2069: args_so_far++;
2070:
2071: if (named && args_so_far < 4 && !MUST_PASS_IN_STACK (mode,type))
2072: return gen_rtx (REG, mode, args_so_far + FIRST_REG_FOR_FUNCTION_ARG);
2073: else
2074: return (struct rtx_def *) 0;
2075: }
2076: else
2077: return (struct rtx_def *) 0;
2078: }
2079:
2080: /* Advance the argument to the next argument position. */
2081:
2082: void
2083: dsp16xx_function_arg_advance (cum, mode, type, named)
2084: CUMULATIVE_ARGS *cum; /* current arg information */
2085: enum machine_mode mode; /* current arg mode */
2086: tree type; /* type of the argument or 0 if lib support */
2087: int named; /* whether or not the argument was named */
2088: {
2089: if (TARGET_REGPARM)
2090: {
2091: if ((*cum & 1) != 0
2092: && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT))
2093: *cum += 1;
2094:
2095: if (mode != BLKmode)
2096: *cum += GET_MODE_SIZE (mode);
2097: else
2098: *cum += int_size_in_bytes (type);
2099: }
2100: }
2101:
2102: void
2103: dsp16xx_file_start ()
2104: {
2105: fprintf (asm_out_file, "#include <%s.h>\n", save_chip_name);
2106: #if 0
2107: if (TARGET_BMU)
2108: fprintf (asm_out_file, "#include <1610.h>\n");
2109: #endif
2110: }
2111:
2112: rtx
2113: gen_tst_reg (x)
2114: rtx x;
2115: {
2116: enum machine_mode mode;
2117:
2118: mode = GET_MODE (x);
2119:
2120: if (mode == QImode)
2121: {
2122: emit_insn (gen_rtx (PARALLEL, VOIDmode,
2123: gen_rtvec (2,
2124: gen_rtx (SET, VOIDmode, cc0_rtx, x),
2125: gen_rtx (CLOBBER, VOIDmode,
2126: gen_rtx (SCRATCH, QImode, 0)))));
2127: }
2128: else if (mode == HImode)
2129: emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, x));
2130: else
2131: fatal ("Illegal mode for gen_tst_reg");
2132:
2133: return cc0_rtx;
2134: }
2135:
2136: rtx
2137: gen_compare_reg (code, x, y)
2138: enum rtx_code code;
2139: rtx x, y;
2140: {
2141: enum machine_mode mode;
2142:
2143: mode = GET_MODE (x);
2144: /* For floating point compare insns, a call is generated so don't
2145: do anything here. */
2146:
2147: if (GET_MODE_CLASS (mode) == MODE_FLOAT)
2148: return cc0_rtx;
2149:
2150: if (mode == QImode)
2151: {
2152: if (code == GTU || code == GEU ||
2153: code == LTU || code == LEU)
2154: {
2155: emit_insn (gen_rtx (PARALLEL, VOIDmode,
2156: gen_rtvec (3,
2157: gen_rtx (SET, VOIDmode, cc0_rtx,
2158: gen_rtx (COMPARE, mode, x, y)),
2159: gen_rtx (CLOBBER, VOIDmode,
2160: gen_rtx (SCRATCH, QImode, 0)),
2161: gen_rtx (CLOBBER, VOIDmode,
2162: gen_rtx (SCRATCH, QImode, 0)))));
2163: }
2164: else
2165: {
2166: emit_insn (gen_rtx (PARALLEL, VOIDmode,
2167: gen_rtvec (3,
2168: gen_rtx (SET, VOIDmode, cc0_rtx,
2169: gen_rtx (COMPARE, mode, x, y)),
2170: gen_rtx (CLOBBER, VOIDmode,
2171: gen_rtx (SCRATCH, QImode, 0)),
2172: gen_rtx (CLOBBER, VOIDmode,
2173: gen_rtx (SCRATCH, QImode, 0)))));
2174: }
2175: }
2176: else if (mode == HImode)
2177: {
2178: if (code == GTU || code == GEU ||
2179: code == LTU || code == LEU)
2180: {
2181: #if 1
2182: emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (5,
2183: gen_rtx (SET, VOIDmode, cc0_rtx, gen_rtx (COMPARE, VOIDmode, x, y)),
2184: gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, QImode, 0)),
2185: gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, QImode, 0)),
2186: gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, QImode, 0)),
2187: gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, QImode, 0)))));
2188: #else
2189: if (!dsp16xx_ucmphi2_libcall)
2190: dsp16xx_ucmphi2_libcall = gen_rtx (SYMBOL_REF, Pmode, UCMPHI2_LIBCALL);
2191: emit_library_call (dsp16xx_ucmphi2_libcall, 1, HImode, 2,
2192: x, HImode, y, HImode);
2193: emit_insn (gen_tsthi_1 (copy_to_reg(hard_libcall_value (HImode))));
2194: #endif
2195: }
2196: else
2197: emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx,
2198: gen_rtx (COMPARE, VOIDmode, force_reg(HImode, x),
2199: force_reg(HImode,y))));
2200: }
2201: else
2202: fatal ("Illegal mode for integer comparison in gen_compare_reg");
2203:
2204: return cc0_rtx;
2205: }
2206:
2207: char *
2208: output_block_move (operands)
2209: rtx operands[];
2210: {
2211: int loop_count = INTVAL(operands[2]);
2212: rtx xoperands[4];
2213:
2214: fprintf (asm_out_file, "\tdo %d {\n", loop_count);
2215: xoperands[0] = operands[4];
2216: xoperands[1] = operands[1];
2217: output_asm_insn ("%0=*%1++", xoperands);
2218:
2219: xoperands[0] = operands[0];
2220: xoperands[1] = operands[4];
2221: output_asm_insn ("*%0++=%1", xoperands);
2222:
2223: fprintf (asm_out_file, "\t}\n");
2224: return "";
2225: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.