1750a.md, [...]: Use GEN_INT consistently.
[gcc.git] / gcc / config / gmicro / gmicro.c
1 /* Subroutines for insn-output.c for the Gmicro.
2 Ported by Masanobu Yuhara, Fujitsu Laboratories LTD.
3 (yuhara@flab.fujitsu.co.jp)
4
5 Copyright (C) 1990, 1991, 1997 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, 59 Temple Place - Suite 330,
25 Boston, MA 02111-1307, USA. */
26
27
28 #include "config.h"
29 #include <stdio.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_INT (CONST_DOUBLE_HIGH (operands[1]));
639 output_asm_insn ("mov.w %1,%0", xoperands);
640 operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
641 return "mov.w %1,%0";
642 }
643 else
644 {
645 return output_move_double (operands); /* ?????? */
646 }
647 }
648
649 char *
650 output_move_const_single (operands)
651 rtx *operands;
652 {
653 int code = standard_fpu_constant_p (operands[1]);
654 static char buf[40];
655
656 if (FPU_REG_P (operands[0]))
657 {
658 if (code != 0)
659 {
660 sprintf (buf, "fmvr from%d,%%0.s", code);
661 return buf;
662 }
663 return "fmov.s %f1,%0";
664 }
665 else
666 return "mov.w %f1,%0";
667 }
668
669
670 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
671 from the "fmvr" instruction of the Gmicro FPU.
672 The value, anded with 0xff, gives the code to use in fmovecr
673 to get the desired constant. */
674
675 u.i[0] = CONST_DOUBLE_LOW (x);
676 u.i[1] = CONST_DOUBLE_HIGH (x);
677 d = u.d;
678
679 if (d == 0.0) /* +0.0 */
680 return 0x0;
681 /* Note: there are various other constants available
682 but it is a nuisance to put in their values here. */
683 if (d == 1.0) /* +1.0 */
684 return 0x1;
685
686 /*
687 * Stuff that looks different if it's single or double
688 */
689 if (GET_MODE (x) == SFmode)
690 {
691 if (d == S_PI)
692 return 0x2;
693 if (d == (S_PI / 2.0))
694 return 0x3;
695 if (d == S_E)
696 return 0x4;
697 if (d == S_LOGEof2)
698 return 0x5;
699 if (d == S_LOGEof10)
700 return 0x6;
701 if (d == S_LOG10of2)
702 return 0x7;
703 if (d == S_LOG10ofE)
704 return 0x8;
705 if (d == S_LOG2ofE)
706 return 0x9;
707 }
708 else
709 {
710 if (d == D_PI)
711 return 0x2;
712 if (d == (D_PI / 2.0))
713 return 0x3;
714 if (d == D_E)
715 return 0x4;
716 if (d == D_LOGEof2)
717 return 0x5;
718 if (d == D_LOGEof10)
719 return 0x6;
720 if (d == D_LOG10of2)
721 return 0x7;
722 if (d == D_LOG10ofE)
723 return 0x8;
724 if (d == D_LOG2ofE)
725 return 0x9;
726 }
727
728 return 0;
729 }
730
731 #undef S_PI
732 #undef D_PI
733 #undef S_E
734 #undef D_E
735 #undef S_LOGEof2
736 #undef D_LOGEof2
737 #undef S_LOGEof10
738 #undef D_LOGEof10
739 #undef S_LOG10of2
740 #undef D_LOG10of2
741 #undef S_LOG10ofE
742 #undef D_LOG10ofE
743 #undef S_LOG2ofE
744 #undef D_LOG2ofE
745
746 /* dest should be operand 0 */
747 /* imm should be operand 1 */
748
749 extern char *sub_imm_word ();
750
751 char *
752 add_imm_word (imm, dest, immp)
753 int imm;
754 rtx dest, *immp;
755 {
756 int is_reg, short_ok;
757
758
759 if (imm < 0)
760 {
761 *immp = GEN_INT (-imm);
762 return sub_imm_word (-imm, dest);
763 }
764
765 if (imm == 0)
766 return "mov:l.w #0,%0";
767
768 short_ok = short_format_ok (dest);
769
770 if (short_ok && imm <= 8)
771 return "add:q %1,%0.w";
772
773 if (imm < 128)
774 return "add:e %1,%0.w";
775
776 is_reg = (GET_CODE (dest) == REG);
777
778 if (is_reg)
779 return "add:l %1,%0.w";
780
781 if (short_ok)
782 return "add:i %1,%0.w";
783
784 return "add %1,%0.w";
785 }
786
787 char *
788 sub_imm_word (imm, dest, immp)
789 int imm;
790 rtx dest, *immp;
791 {
792 int is_reg, short_ok;
793
794 if (imm < 0 && imm != 0x80000000)
795 {
796 *immp = GEN_INT (-imm);
797 return add_imm_word (-imm, dest);
798 }
799
800 if (imm == 0)
801 return "mov:z.w #0,%0";
802
803 short_ok = short_format_ok (dest);
804
805 if (short_ok && imm <= 8)
806 return "sub:q %1,%0.w";
807
808 if (imm < 128)
809 return "sub:e %1,%0.w";
810
811 is_reg = (GET_CODE (dest) == REG);
812
813 if (is_reg)
814 return "sub:l %1,%0.w";
815
816 if (short_ok)
817 return "sub:i %1,%0.w";
818
819 return "sub %1,%0.w";
820 }
821
822 int
823 short_format_ok (x)
824 rtx x;
825 {
826 rtx x0, x1;
827
828 if (GET_CODE (x) == REG)
829 return 1;
830
831 if (GET_CODE (x) == MEM
832 && GET_CODE (XEXP (x, 0)) == PLUS)
833 {
834 x0 = XEXP (XEXP (x, 0), 0);
835 x1 = XEXP (XEXP (x, 0), 1);
836 return ((GET_CODE (x0) == REG
837 && CONSTANT_P (x1)
838 && ((unsigned) (INTVAL (x1) + 0x8000) < 0x10000))
839 ||
840 (GET_CODE (x1) == REG
841 && CONSTANT_P (x0)
842 && ((unsigned) (INTVAL (x0) + 0x8000) < 0x10000)));
843 }
844
845 return 0;
846 }
847
848 myoutput_sp_adjust (file, op, fsize)
849 FILE *file;
850 char *op;
851 int fsize;
852 {
853 if (fsize == 0)
854 ;
855 else if (fsize < 8)
856 fprintf (file, "\t%s:q #%d,sp.w\n", op, fsize);
857 else if (fsize < 128)
858 fprintf (file, "\t%s:e #%d,sp.w\n", op, fsize);
859 else
860 fprintf (file, "\t%s:l #%d,sp.w\n", op, fsize);
861 }
862
863
864 char *
865 mov_imm_word (imm, dest)
866 int imm;
867 rtx dest;
868 {
869 int is_reg, short_ok;
870
871 if (imm == 0)
872 return "mov:z.w #0,%0";
873
874 short_ok = short_format_ok (dest);
875
876 if (short_ok && imm > 0 && imm <= 8)
877 return "mov:q %1,%0.w";
878
879 if (-128 <= imm && imm < 128)
880 return "mov:e %1,%0.w";
881
882 is_reg = (GET_CODE (dest) == REG);
883
884 if (is_reg)
885 return "mov:l %1,%0.w";
886
887 if (short_ok)
888 return "mov:i %1,%0.w";
889
890 return "mov %1,%0.w";
891 }
892
893 char *
894 cmp_imm_word (imm, dest)
895 int imm;
896 rtx dest;
897 {
898 int is_reg, short_ok;
899
900 if (imm == 0)
901 return "cmp:z.w #0,%0";
902
903 short_ok = short_format_ok (dest);
904
905 if (short_ok && imm >0 && imm <= 8)
906 return "cmp:q %1,%0.w";
907
908 if (-128 <= imm && imm < 128)
909 return "cmp:e %1,%0.w";
910
911 is_reg = (GET_CODE (dest) == REG);
912
913 if (is_reg)
914 return "cmp:l %1,%0.w";
915
916 if (short_ok)
917 return "cmp:i %1,%0.w";
918
919 return "cmp %1,%0.w";
920 }
921
922 char *
923 push_imm_word (imm)
924 int imm;
925 {
926 if (imm == 0)
927 return "mov:z.w #0,%-";
928
929 if (imm > 0 && imm <= 8)
930 return "mov:q %1,%-.w";
931
932 if (-128 <= imm && imm < 128)
933 return "mov:e %1,%-.w";
934
935 return "mov:g %1,%-.w";
936
937 /* In some cases, g-format may be better than I format.??
938 return "mov %1,%0.w";
939 */
940 }
941
942 my_signed_comp (insn)
943 rtx insn;
944 {
945 rtx my_insn;
946
947 my_insn = NEXT_INSN (insn);
948 if (GET_CODE (my_insn) != JUMP_INSN)
949 {
950 fprintf (stderr, "my_signed_comp: Not Jump_insn ");
951 myabort (GET_CODE (my_insn));
952 }
953 my_insn = PATTERN (my_insn);
954 if (GET_CODE (my_insn) != SET)
955 {
956 fprintf (stderr, "my_signed_comp: Not Set ");
957 myabort (GET_CODE (my_insn));
958 }
959 my_insn = SET_SRC (my_insn);
960 if (GET_CODE (my_insn) != IF_THEN_ELSE)
961 {
962 fprintf (stderr, "my_signed_comp: Not if_then_else ");
963 myabort (GET_CODE (my_insn));
964 }
965 switch (GET_CODE (XEXP (my_insn, 0)))
966 {
967 case NE:
968 case EQ:
969 case GE:
970 case GT:
971 case LE:
972 case LT:
973 return 1;
974 case GEU:
975 case GTU:
976 case LEU:
977 case LTU:
978 return 0;
979 }
980 fprintf (stderr, "my_signed_comp: Not cccc ");
981 myabort (GET_CODE (XEXP (my_insn, 0)));
982 }