|
|
1.1 root 1: /* Subroutines for insn-output.c for the Gmicro.
2: Ported by Masanobu Yuhara, Fujitsu Laboratories LTD.
3: ([email protected])
4:
5: Copyright (C) 1990, 1991 Free Software Foundation, Inc.
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: Among other things, the copyright
20: notice and this notice must be preserved on all copies.
21:
22: You should have received a copy of the GNU General Public License
23: along with GNU CC; see the file COPYING. If not, write to
1.1.1.2 ! root 24: the Free Software Foundation, 59 Temple Place - Suite 330,
! 25: Boston, MA 02111-1307, USA. */
1.1 root 26:
27:
28: #include <stdio.h>
29: #include "config.h"
30: #include "rtl.h"
31: #include "regs.h"
32: #include "hard-reg-set.h"
33: #include "real.h"
34: #include "insn-config.h"
35: #include "conditions.h"
36: #include "insn-flags.h"
37: #include "output.h"
38: #include "insn-attr.h"
39:
40: extern char *rtx_name[];
41:
42: mypr (s, a1, a2, a3, a4, a5)
43: char *s;
44: int a1, a2, a3, a4, a5;
45: {
46: fprintf (stderr, s, a1, a2, a3, a4, a5);
47: }
48:
49: myprcode (i)
50: int i;
51: {
52: if (i < 0 || i > 90)
53: fprintf (stderr, "code = %d\n", i);
54: else
55: fprintf (stderr, "code = %s\n", rtx_name[i]);
56: }
57:
58: myabort (i)
59: int i;
60: {
61: fprintf (stderr, "myabort");
62: myprcode (i);
63: }
64:
65:
66: /* This is how to output an ascii string. */
67: /* See ASM_OUTPUT_ASCII in gmicro.h. */
68: output_ascii (file, p, size)
69: FILE *file;
70: char *p;
71: int size;
72: {
73: int i;
74: int in_quote = 0;
75: register int c;
76:
77: fprintf (file, "\t.sdata ");
78:
79: for (i = 0; i < size; i++)
80: {
81: c = p[i];
82: if (c >= ' ' && c < 0x7f)
83: {
84: if (!in_quote)
85: {
86: putc ('"', file);
87: in_quote = 1;
88: }
89: putc (c, file);
90: }
91: else
92: {
93: if (in_quote)
94: {
95: putc ('"', file);
96: in_quote = 0;
97: }
98: fprintf (file, "<%d>", c);
99: }
100: }
101: if (in_quote)
102: putc ('"', file);
103: putc ('\n', file);
104: }
105:
106:
107: /* call this when GET_CODE (index) is MULT. */
108: print_scaled_index (file, index)
109: FILE *file;
110: register rtx index;
111: {
112: register rtx ireg;
113: int scale;
114:
115: if (GET_CODE (XEXP (index, 0)) == REG)
116: {
117: ireg = XEXP (index, 0);
118: scale = INTVAL (XEXP (index, 1));
119: }
120: else
121: {
122: ireg = XEXP (index, 1);
123: scale = INTVAL (XEXP (index, 0));
124: }
125: if (scale == 1)
126: fprintf (file, "%s", reg_names[REGNO (ireg)]);
127: else
128: fprintf (file, "%s*%d", reg_names[REGNO (ireg)], scale);
129: }
130:
131:
132: print_operand_address (file, addr)
133: FILE *file;
134: register rtx addr;
135: {
136: register rtx xtmp0, xtmp1, breg, ixreg;
137: int scale;
138: int needcomma = 0;
139: rtx offset;
140:
141: fprintf (file, "@");
142: retry:
143: switch (GET_CODE (addr))
144: {
145: case MEM:
146: fprintf (file, "@");
147: addr = XEXP (addr, 0);
148: goto retry;
149:
150: case REG:
151: fprintf (file, "%s", reg_names[REGNO (addr)]);
152: break;
153:
154: case MULT:
155: print_scaled_index (file, addr);
156: break;
157:
158: case PRE_DEC:
159: fprintf (file, "-%s", reg_names[REGNO (XEXP (addr, 0))]);
160: break;
161:
162: case POST_INC:
163: fprintf (file, "%s+", reg_names[REGNO (XEXP (addr, 0))]);
164: break;
165:
166: case PLUS:
167: xtmp0 = XEXP (addr, 0);
168: xtmp1 = XEXP (addr, 1);
169: ixreg = 0; breg = 0;
170: offset = 0;
171: if (CONSTANT_ADDRESS_P (xtmp0))
172: {
173: offset = xtmp0;
174: breg = xtmp1;
175: }
176: else if (CONSTANT_ADDRESS_P (xtmp1))
177: {
178: offset = xtmp1;
179: breg = xtmp0;
180: }
181: else
182: {
183: goto NOT_DISP;
184: }
185:
186: if (REG_CODE_BASE_P (breg))
187: goto PRINT_MEM;
188:
189: if (GET_CODE (breg) == MULT)
190: {
191: if (REG_CODE_INDEX_P (XEXP (breg, 0)))
192: {
193: ixreg = XEXP (breg, 0);
194: scale = INTVAL (XEXP (breg, 1));
195: breg = 0;
196: }
197: else
198: {
199: ixreg = XEXP (breg, 1);
200: scale = INTVAL (XEXP (breg, 0));
201: breg = 0;
202: }
203: goto PRINT_MEM;
204: }
205:
206: /* GET_CODE (breg) must be PLUS here. */
207: xtmp0 = XEXP (breg, 0);
208: xtmp1 = XEXP (breg, 1);
209: if (REG_CODE_BASE_P (xtmp0))
210: {
211: breg = xtmp0;
212: xtmp0 = xtmp1;
213: }
214: else
215: {
216: breg = xtmp1;
217: /* xtmp0 = xtmp0; */
218: }
219:
220: if (GET_CODE (xtmp0) == MULT)
221: {
222: if (REG_CODE_INDEX_P (XEXP (xtmp0, 0)))
223: {
224: ixreg = XEXP (xtmp0, 0);
225: scale = INTVAL (XEXP (xtmp0, 1));
226: }
227: else
228: {
229: ixreg = XEXP (xtmp0, 1);
230: scale = INTVAL (XEXP (xtmp0, 0));
231: }
232: }
233: else
234: {
235: ixreg = xtmp0;
236: scale = 1;
237: }
238: goto PRINT_MEM;
239:
240: NOT_DISP:
241: if (REG_CODE_BASE_P (xtmp0))
242: {
243: breg = xtmp0;
244: xtmp0 = xtmp1;
245: }
246: else if (REG_CODE_BASE_P (xtmp1))
247: {
248: breg = xtmp1;
249: /* xtmp0 = xtmp0; */
250: }
251: else
252: goto NOT_BASE;
253:
254: if (REG_CODE_INDEX_P (xtmp0))
255: {
256: ixreg = xtmp0;
257: scale = 1;
258: goto PRINT_MEM;
259: }
260: else if (CONSTANT_ADDRESS_P (xtmp0))
261: {
262: offset = xtmp0;
263: goto PRINT_MEM;
264: }
265: else if (GET_CODE (xtmp0) == MULT)
266: {
267: if (REG_CODE_INDEX_P (XEXP (xtmp0, 0)))
268: {
269: ixreg = XEXP (xtmp0, 0);
270: scale = INTVAL (XEXP (xtmp0, 1));
271: }
272: else
273: {
274: ixreg = XEXP (xtmp0, 1);
275: scale = INTVAL (XEXP (xtmp0, 0));
276: }
277: goto PRINT_MEM;
278: }
279:
280: /* GET_CODE (xtmp0) must be PLUS. */
281: xtmp1 = XEXP (xtmp0, 1);
282: xtmp0 = XEXP (xtmp0, 0);
283:
284: if (CONSTANT_ADDRESS_P (xtmp0))
285: {
286: offset = xtmp0;
287: xtmp0 = xtmp1;
288: }
289: else
290: {
291: offset = xtmp1;
292: /* xtmp0 = xtmp0; */
293: }
294:
295: if (REG_CODE_INDEX_P (xtmp0))
296: {
297: ixreg = xtmp0;
298: }
299: else
300: { /* GET_CODE (xtmp0) must be MULT. */
301: if (REG_CODE_INDEX_P (XEXP (xtmp0, 0)))
302: {
303: ixreg = XEXP (xtmp0, 0);
304: scale = INTVAL (XEXP (xtmp0, 1));
305: }
306: else
307: {
308: ixreg = XEXP (xtmp0, 1);
309: scale = INTVAL (XEXP (xtmp0, 0));
310: }
311: }
312: goto PRINT_MEM;
313:
314: NOT_BASE:
315: if (GET_CODE (xtmp0) == PLUS)
316: {
317: ixreg = xtmp1;
318: /* xtmp0 = xtmp0; */
319: }
320: else
321: {
322: ixreg = xtmp0;
323: xtmp0 = xtmp1;
324: }
325:
326: if (REG_CODE_INDEX_P (ixreg))
327: {
328: scale = 1;
329: }
330: else if (REG_CODE_INDEX_P (XEXP (ixreg, 0)))
331: {
332: scale = INTVAL (XEXP (ixreg, 1));
333: ixreg = XEXP (ixreg, 0);
334: }
335: else
336: { /* was else if with no condition. OK ??? */
337: scale = INTVAL (XEXP (ixreg, 0));
338: ixreg = XEXP (ixreg, 1);
339: }
340:
341: if (REG_CODE_BASE_P (XEXP (xtmp0, 0)))
342: {
343: breg = XEXP (xtmp0, 0);
344: offset = XEXP (xtmp0, 1);
345: }
346: else
347: {
348: breg = XEXP (xtmp0, 1);
349: offset = XEXP (xtmp0, 0);
350: }
351:
352: PRINT_MEM:
353: if (breg == 0 && ixreg == 0)
354: {
355: output_address (offset);
356: break;
357: }
358: else if (ixreg == 0 && offset == 0)
359: {
360: fprintf (file, "%s", reg_names[REGNO (breg)]);
361: break;
362: }
363: else
364: {
365: fprintf (file, "(");
366: if (offset != 0)
367: {
368: output_addr_const (file, offset);
369: needcomma = 1;
370: }
371: if (breg != 0)
372: {
373: if (needcomma)
374: fprintf (file, ",");
375: fprintf (file, "%s", reg_names[REGNO (breg)]);
376: needcomma = 1;
377: }
378: if (ixreg != 0)
379: {
380: if (needcomma)
381: fprintf (file, ",");
382: fprintf (file, "%s", reg_names[REGNO (ixreg)]);
383: if (scale != 1)
384: fprintf (file,"*%d", scale);
385: }
386: fprintf (file, ")");
387:
388: break;
389: }
390:
391: default:
392: output_addr_const (file, addr);
393: }
394: }
395:
396:
397:
398: /* Return a REG that occurs in ADDR with coefficient 1.
399: ADDR can be effectively incremented by incrementing REG. */
400:
401: static rtx
402: find_addr_reg (addr)
403: rtx addr;
404: {
405: while (GET_CODE (addr) == PLUS)
406: {
407: if (GET_CODE (XEXP (addr, 0)) == REG)
408: addr = XEXP (addr, 0);
409: else if (GET_CODE (XEXP (addr, 1)) == REG)
410: addr = XEXP (addr, 1);
411: else if (GET_CODE (XEXP (addr, 0)) == PLUS)
412: addr = XEXP (addr, 0);
413: else if (GET_CODE (XEXP (addr, 1)) == PLUS)
414: addr = XEXP (addr, 1);
415: }
416: if (GET_CODE (addr) == REG)
417: return addr;
418: return 0;
419: }
420:
421:
422: /* Return the best assembler insn template
423: for moving operands[1] into operands[0] as a fullword. */
424:
425: static char *
426: singlemove_string (operands)
427: rtx *operands;
428: {
429: if (FPU_REG_P (operands[0]) || FPU_REG_P (operands[1]))
430: {
431: if (GREG_P (operands[0]) || GREG_P (operands[1]))
432: {
433: myabort (101); /* Not Supported yet !! */
434: }
435: else
436: {
437: return "fmov.s %1,%0";
438: }
439: }
440: return "mov.w %1,%0";
441: }
442:
443:
444: /* Output assembler code to perform a doubleword move insn
445: with operands OPERANDS. */
446:
447: char *
448: output_move_double (operands)
449: rtx *operands;
450: {
451: enum
452: { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP }
453: optype0, optype1;
454: rtx latehalf[2];
455: rtx addreg0 = 0, addreg1 = 0;
456:
457: /* First classify both operands. */
458:
459: if (REG_P (operands[0]))
460: optype0 = REGOP;
461: else if (offsettable_memref_p (operands[0]))
462: optype0 = OFFSOP;
463: else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
464: optype0 = POPOP;
465: else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
466: optype0 = PUSHOP;
467: else if (GET_CODE (operands[0]) == MEM)
468: optype0 = MEMOP;
469: else
470: optype0 = RNDOP;
471:
472: if (REG_P (operands[1]))
473: optype1 = REGOP;
474: else if (CONSTANT_P (operands[1]))
475: optype1 = CNSTOP;
476: else if (offsettable_memref_p (operands[1]))
477: optype1 = OFFSOP;
478: else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
479: optype1 = POPOP;
480: else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
481: optype1 = PUSHOP;
482: else if (GET_CODE (operands[1]) == MEM)
483: optype1 = MEMOP;
484: else
485: optype1 = RNDOP;
486:
487: /* Check for the cases that the operand constraints are not
488: supposed to allow to happen. Abort if we get one,
489: because generating code for these cases is painful. */
490:
491: if (optype0 == RNDOP || optype1 == RNDOP)
492: myabort (102);
493:
494: /* If one operand is decrementing and one is incrementing
495: decrement the former register explicitly
496: and change that operand into ordinary indexing. */
497:
498: if (optype0 == PUSHOP && optype1 == POPOP)
499: {
500: operands[0] = XEXP (XEXP (operands[0], 0), 0);
501: output_asm_insn ("sub.w %#8,%0", operands);
502: operands[0] = gen_rtx (MEM, DImode, operands[0]);
503: optype0 = OFFSOP;
504: }
505: if (optype0 == POPOP && optype1 == PUSHOP)
506: {
507: operands[1] = XEXP (XEXP (operands[1], 0), 0);
508: output_asm_insn ("sub.w %#8,%1", operands);
509: operands[1] = gen_rtx (MEM, DImode, operands[1]);
510: optype1 = OFFSOP;
511: }
512:
513: /* If an operand is an unoffsettable memory ref, find a register
514: we can increment temporarily to make it refer to the second word. */
515:
516: if (optype0 == MEMOP)
517: addreg0 = find_addr_reg (operands[0]);
518:
519: if (optype1 == MEMOP)
520: addreg1 = find_addr_reg (operands[1]);
521:
522: /* Ok, we can do one word at a time.
523: Normally we do the low-numbered word first,
524: but if either operand is autodecrementing then we
525: do the high-numbered word first.
526:
527: In either case, set up in LATEHALF the operands to use
528: for the high-numbered word and in some cases alter the
529: operands in OPERANDS to be suitable for the low-numbered word. */
530:
531: if (optype0 == REGOP)
532: latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
533: else if (optype0 == OFFSOP)
534: latehalf[0] = adj_offsettable_operand (operands[0], 4);
535: else
536: latehalf[0] = operands[0];
537:
538: if (optype1 == REGOP)
539: latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
540: else if (optype1 == OFFSOP)
541: latehalf[1] = adj_offsettable_operand (operands[1], 4);
542: else if (optype1 == CNSTOP)
543: {
544: if (GET_CODE (operands[1]) == CONST_DOUBLE)
545: split_double (operands[1], &operands[1], &latehalf[1]);
546: else if (CONSTANT_P (operands[1]))
547: latehalf[1] = const0_rtx;
548: }
549: else
550: latehalf[1] = operands[1];
551:
552: /* If insn is effectively movd N(sp),-(sp) then we will do the
553: high word first. We should use the adjusted operand 1 (which is N+4(sp))
554: for the low word as well, to compensate for the first decrement of sp. */
555: if (optype0 == PUSHOP
556: && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
557: && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
558: operands[1] = latehalf[1];
559:
560: /* If one or both operands autodecrementing,
561: do the two words, high-numbered first. */
562:
563: /* Likewise, the first move would clobber the source of the second one,
564: do them in the other order. This happens only for registers;
565: such overlap can't happen in memory unless the user explicitly
566: sets it up, and that is an undefined circumstance. */
567:
568: if (optype0 == PUSHOP || optype1 == PUSHOP
569: || (optype0 == REGOP && optype1 == REGOP
570: && REGNO (operands[0]) == REGNO (latehalf[1])))
571: {
572: /* Make any unoffsettable addresses point at high-numbered word. */
573: if (addreg0)
574: output_asm_insn ("add.w %#4,%0", &addreg0);
575: if (addreg1)
576: output_asm_insn ("add.w %#4,%0", &addreg1);
577:
578: /* Do that word. */
579: output_asm_insn (singlemove_string (latehalf), latehalf);
580:
581: /* Undo the adds we just did. */
582: if (addreg0)
583: output_asm_insn ("sub.w %#4,%0", &addreg0);
584: if (addreg1)
585: output_asm_insn ("sub.w %#4,%0", &addreg1);
586:
587: /* Do low-numbered word. */
588: return singlemove_string (operands);
589: }
590:
591: /* Normal case: do the two words, low-numbered first. */
592:
593: output_asm_insn (singlemove_string (operands), operands);
594:
595: /* Make any unoffsettable addresses point at high-numbered word. */
596: if (addreg0)
597: output_asm_insn ("add.w %#4,%0", &addreg0);
598: if (addreg1)
599: output_asm_insn ("add.w %#4,%0", &addreg1);
600:
601: /* Do that word. */
602: output_asm_insn (singlemove_string (latehalf), latehalf);
603:
604: /* Undo the adds we just did. */
605: if (addreg0)
606: output_asm_insn ("sub.w %#4,%0", &addreg0);
607: if (addreg1)
608: output_asm_insn ("sub.w %#4,%0", &addreg1);
609:
610: return "";
611: }
612:
613: /* Move const_double to floating point register (DF) */
614: char *
615: output_move_const_double (operands)
616: rtx *operands;
617: {
618: int code = standard_fpu_constant_p (operands[1]);
619:
620: if (FPU_REG_P (operands[0]))
621: {
622: if (code != 0)
623: {
624: static char buf[40];
625:
626: sprintf (buf, "fmvr from%d,%%0.d", code);
627: return buf;
628: }
629: else
630: {
631: return "fmov %1,%0.d";
632: }
633: }
634: else if (GREG_P (operands[0]))
635: {
636: rtx xoperands[2];
637: xoperands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
638: xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
639: CONST_DOUBLE_HIGH (operands[1]));
640: output_asm_insn ("mov.w %1,%0", xoperands);
641: operands[1] = gen_rtx (CONST_INT, VOIDmode,
642: CONST_DOUBLE_LOW (operands[1]));
643: return "mov.w %1,%0";
644: }
645: else
646: {
647: return output_move_double (operands); /* ?????? */
648: }
649: }
650:
651: char *
652: output_move_const_single (operands)
653: rtx *operands;
654: {
655: int code = standard_fpu_constant_p (operands[1]);
656: static char buf[40];
657:
658: if (FPU_REG_P (operands[0]))
659: {
660: if (code != 0)
661: {
662: sprintf (buf, "fmvr from%d,%%0.s", code);
663: return buf;
664: }
665: return "fmov.s %f1,%0";
666: }
667: else
668: return "mov.w %f1,%0";
669: }
670:
671:
672: /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
673: from the "fmvr" instruction of the Gmicro FPU.
674: The value, anded with 0xff, gives the code to use in fmovecr
675: to get the desired constant. */
676:
677: u.i[0] = CONST_DOUBLE_LOW (x);
678: u.i[1] = CONST_DOUBLE_HIGH (x);
679: d = u.d;
680:
681: if (d == 0.0) /* +0.0 */
682: return 0x0;
683: /* Note: there are various other constants available
684: but it is a nuisance to put in their values here. */
685: if (d == 1.0) /* +1.0 */
686: return 0x1;
687:
688: /*
689: * Stuff that looks different if it's single or double
690: */
691: if (GET_MODE (x) == SFmode)
692: {
693: if (d == S_PI)
694: return 0x2;
695: if (d == (S_PI / 2.0))
696: return 0x3;
697: if (d == S_E)
698: return 0x4;
699: if (d == S_LOGEof2)
700: return 0x5;
701: if (d == S_LOGEof10)
702: return 0x6;
703: if (d == S_LOG10of2)
704: return 0x7;
705: if (d == S_LOG10ofE)
706: return 0x8;
707: if (d == S_LOG2ofE)
708: return 0x9;
709: }
710: else
711: {
712: if (d == D_PI)
713: return 0x2;
714: if (d == (D_PI / 2.0))
715: return 0x3;
716: if (d == D_E)
717: return 0x4;
718: if (d == D_LOGEof2)
719: return 0x5;
720: if (d == D_LOGEof10)
721: return 0x6;
722: if (d == D_LOG10of2)
723: return 0x7;
724: if (d == D_LOG10ofE)
725: return 0x8;
726: if (d == D_LOG2ofE)
727: return 0x9;
728: }
729:
730: return 0;
731: }
732:
733: #undef S_PI
734: #undef D_PI
735: #undef S_E
736: #undef D_E
737: #undef S_LOGEof2
738: #undef D_LOGEof2
739: #undef S_LOGEof10
740: #undef D_LOGEof10
741: #undef S_LOG10of2
742: #undef D_LOG10of2
743: #undef S_LOG10ofE
744: #undef D_LOG10ofE
745: #undef S_LOG2ofE
746: #undef D_LOG2ofE
747:
748: /* dest should be operand 0 */
749: /* imm should be operand 1 */
750:
751: extern char *sub_imm_word ();
752:
753: char *
754: add_imm_word (imm, dest, immp)
755: int imm;
756: rtx dest, *immp;
757: {
758: int is_reg, short_ok;
759:
760:
761: if (imm < 0)
762: {
763: *immp = gen_rtx (CONST_INT, VOIDmode, -imm);
764: return sub_imm_word (-imm, dest);
765: }
766:
767: if (imm == 0)
768: return "mov:l.w #0,%0";
769:
770: short_ok = short_format_ok (dest);
771:
772: if (short_ok && imm <= 8)
773: return "add:q %1,%0.w";
774:
775: if (imm < 128)
776: return "add:e %1,%0.w";
777:
778: is_reg = (GET_CODE (dest) == REG);
779:
780: if (is_reg)
781: return "add:l %1,%0.w";
782:
783: if (short_ok)
784: return "add:i %1,%0.w";
785:
786: return "add %1,%0.w";
787: }
788:
789: char *
790: sub_imm_word (imm, dest, immp)
791: int imm;
792: rtx dest, *immp;
793: {
794: int is_reg, short_ok;
795:
796: if (imm < 0 && imm != 0x80000000)
797: {
798: *immp = gen_rtx (CONST_INT, VOIDmode, -imm);
799: return add_imm_word (-imm, dest);
800: }
801:
802: if (imm == 0)
803: return "mov:z.w #0,%0";
804:
805: short_ok = short_format_ok (dest);
806:
807: if (short_ok && imm <= 8)
808: return "sub:q %1,%0.w";
809:
810: if (imm < 128)
811: return "sub:e %1,%0.w";
812:
813: is_reg = (GET_CODE (dest) == REG);
814:
815: if (is_reg)
816: return "sub:l %1,%0.w";
817:
818: if (short_ok)
819: return "sub:i %1,%0.w";
820:
821: return "sub %1,%0.w";
822: }
823:
824: int
825: short_format_ok (x)
826: rtx x;
827: {
828: rtx x0, x1;
829:
830: if (GET_CODE (x) == REG)
831: return 1;
832:
833: if (GET_CODE (x) == MEM
834: && GET_CODE (XEXP (x, 0)) == PLUS)
835: {
836: x0 = XEXP (XEXP (x, 0), 0);
837: x1 = XEXP (XEXP (x, 0), 1);
838: return ((GET_CODE (x0) == REG
839: && CONSTANT_P (x1)
840: && ((unsigned) (INTVAL (x1) + 0x8000) < 0x10000))
841: ||
842: (GET_CODE (x1) == REG
843: && CONSTANT_P (x0)
844: && ((unsigned) (INTVAL (x0) + 0x8000) < 0x10000)));
845: }
846:
847: return 0;
848: }
849:
850: myoutput_sp_adjust (file, op, fsize)
851: FILE *file;
852: char *op;
853: int fsize;
854: {
855: if (fsize == 0)
856: ;
857: else if (fsize < 8)
858: fprintf (file, "\t%s:q #%d,sp.w\n", op, fsize);
859: else if (fsize < 128)
860: fprintf (file, "\t%s:e #%d,sp.w\n", op, fsize);
861: else
862: fprintf (file, "\t%s:l #%d,sp.w\n", op, fsize);
863: }
864:
865:
866: char *
867: mov_imm_word (imm, dest)
868: int imm;
869: rtx dest;
870: {
871: int is_reg, short_ok;
872:
873: if (imm == 0)
874: return "mov:z.w #0,%0";
875:
876: short_ok = short_format_ok (dest);
877:
878: if (short_ok && imm > 0 && imm <= 8)
879: return "mov:q %1,%0.w";
880:
881: if (-128 <= imm && imm < 128)
882: return "mov:e %1,%0.w";
883:
884: is_reg = (GET_CODE (dest) == REG);
885:
886: if (is_reg)
887: return "mov:l %1,%0.w";
888:
889: if (short_ok)
890: return "mov:i %1,%0.w";
891:
892: return "mov %1,%0.w";
893: }
894:
895: char *
896: cmp_imm_word (imm, dest)
897: int imm;
898: rtx dest;
899: {
900: int is_reg, short_ok;
901:
902: if (imm == 0)
903: return "cmp:z.w #0,%0";
904:
905: short_ok = short_format_ok (dest);
906:
907: if (short_ok && imm >0 && imm <= 8)
908: return "cmp:q %1,%0.w";
909:
910: if (-128 <= imm && imm < 128)
911: return "cmp:e %1,%0.w";
912:
913: is_reg = (GET_CODE (dest) == REG);
914:
915: if (is_reg)
916: return "cmp:l %1,%0.w";
917:
918: if (short_ok)
919: return "cmp:i %1,%0.w";
920:
921: return "cmp %1,%0.w";
922: }
923:
924: char *
925: push_imm_word (imm)
926: int imm;
927: {
928: if (imm == 0)
929: return "mov:z.w #0,%-";
930:
931: if (imm > 0 && imm <= 8)
932: return "mov:q %1,%-.w";
933:
934: if (-128 <= imm && imm < 128)
935: return "mov:e %1,%-.w";
936:
937: return "mov:g %1,%-.w";
938:
939: /* In some cases, g-format may be better than I format.??
940: return "mov %1,%0.w";
941: */
942: }
943:
944: my_signed_comp (insn)
945: rtx insn;
946: {
947: rtx my_insn;
948:
949: my_insn = NEXT_INSN (insn);
950: if (GET_CODE (my_insn) != JUMP_INSN)
951: {
952: fprintf (stderr, "my_signed_comp: Not Jump_insn ");
953: myabort (GET_CODE (my_insn));
954: }
955: my_insn = PATTERN (my_insn);
956: if (GET_CODE (my_insn) != SET)
957: {
958: fprintf (stderr, "my_signed_comp: Not Set ");
959: myabort (GET_CODE (my_insn));
960: }
961: my_insn = SET_SRC (my_insn);
962: if (GET_CODE (my_insn) != IF_THEN_ELSE)
963: {
964: fprintf (stderr, "my_signed_comp: Not if_then_else ");
965: myabort (GET_CODE (my_insn));
966: }
967: switch (GET_CODE (XEXP (my_insn, 0)))
968: {
969: case NE:
970: case EQ:
971: case GE:
972: case GT:
973: case LE:
974: case LT:
975: return 1;
976: case GEU:
977: case GTU:
978: case LEU:
979: case LTU:
980: return 0;
981: }
982: fprintf (stderr, "my_signed_comp: Not cccc ");
983: myabort (GET_CODE (XEXP (my_insn, 0)));
984: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.