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