OSDN Git Service

(cmphi): Fixed when next CC user is unsigned.
[pf3gnuchains/gcc-fork.git] / gcc / config / 1750a / 1750a.c
1 /* Subroutines for insn-output.c for MIL-STD-1750.
2    Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
3    Contributed by O.M.Kellogg, DASA (kellogg@space.otn.dasa.de)
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 1, 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, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 #ifndef FILE
23 #include <stdio.h>
24 #endif
25 #include <string.h>
26
27 #define __datalbl
28 #include "config.h"
29 #include "rtl.h"
30 #include "tree.h"
31 #include "expr.h"
32 #define HAVE_cc0
33 #include "conditions.h"
34 #include "real.h"
35 #include "regs.h"
36
37 struct datalabel_array datalbl[DATALBL_ARRSIZ];
38 int datalbl_ndx = -1;
39 struct jumplabel_array jmplbl[JMPLBL_ARRSIZ];
40 int jmplbl_ndx = -1;
41 int label_pending = 0, program_counter = 0;
42 enum section current_section = Normal;
43 char *sectname[4] =
44 {"Init", "Normal", "Konst", "Static"};
45
46 int
47 notice_update_cc (exp)
48      rtx exp;
49 {
50   if (GET_CODE (exp) == SET)
51     {
52       enum rtx_code src_code = GET_CODE (SET_SRC (exp));
53       /* Jumps do not alter the cc's.  */
54       if (SET_DEST (exp) == pc_rtx)
55         return;
56       /* Moving a register or constant into memory doesn't alter the cc's. */
57       if (GET_CODE (SET_DEST (exp)) == MEM
58           && (src_code == REG || src_code == CONST_INT))
59         return;
60       /* Function calls clobber the cc's.  */
61       if (src_code == CALL)
62         {
63           CC_STATUS_INIT;
64           return;
65         }
66       /* Emulated longword bit-ops leave cc's incorrect */
67       if (GET_MODE (SET_DEST (exp)) == HImode ?
68                src_code == AND || src_code == IOR ||
69                src_code == XOR || src_code == NOT : 0)
70         {
71           CC_STATUS_INIT;
72           return;
73         }
74       /* Tests and compares set the cc's in predictable ways.  */
75       if (SET_DEST (exp) == cc0_rtx)
76         {
77           CC_STATUS_INIT;
78           cc_status.value1 = SET_SRC (exp);
79           return;
80         }
81       /* Anything else will set cc_status. */
82       cc_status.flags = CC_NO_OVERFLOW;
83       cc_status.value1 = SET_SRC (exp);
84       cc_status.value2 = SET_DEST (exp);
85       return;
86     }
87   else if (GET_CODE (exp) == PARALLEL
88            && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
89     {
90       if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
91         return;
92       if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
93         {
94           CC_STATUS_INIT;
95           cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
96           return;
97         }
98       CC_STATUS_INIT;
99     }
100   else
101     {
102       CC_STATUS_INIT;
103     }
104 }
105
106
107 rtx
108 function_arg (cum, mode, type, named)
109      int cum;
110      enum machine_mode mode;
111      tree type;
112      int named;
113 {
114   int size;
115
116   if (MUST_PASS_IN_STACK (mode, type))
117     return (rtx) 0;
118   if (mode == BLKmode)
119     size = int_size_in_bytes (type);
120   else
121     size = GET_MODE_SIZE (mode);
122   if (cum + size < 12)
123     return gen_rtx (REG, mode, cum);
124   else
125     return (rtx) 0;
126 }
127
128
129 double
130 get_double (x)
131      rtx x;
132 {
133   union
134     {
135       double d;
136       long i[2];
137     }
138   du;
139
140   du.i[0] = CONST_DOUBLE_LOW (x);
141   du.i[1] = CONST_DOUBLE_HIGH (x);
142   return du.d;
143 }
144
145 char *
146 float_label (code, value)
147      char code;
148      double value;
149 {
150   int i = 1;
151   static char label[32];
152   char *p;
153
154   label[0] = code;
155   p = label + 1;
156   sprintf (p, "%lf", value);
157   while (*p)
158     {
159       *p = (*p == '+') ? 'p' :
160         (*p == '-') ? 'm' : *p;
161       p++;
162     }
163   return xstrdup (label);
164 }
165
166
167 char *
168 movcnt_regno_adjust (op)
169      rtx *op;
170 {
171   static char outstr[80];
172   int op0r = REGNO (op[0]), op1r = REGNO (op[1]), op2r = REGNO (op[2]);
173 #define dstreg op0r
174 #define srcreg op1r
175 #define cntreg op2r
176 #define cntreg_1750 (op0r + 1)
177
178   if (cntreg == cntreg_1750)
179     sprintf (outstr, "mov r%d,r%d", op0r, op1r);
180   else if (dstreg + 1 == srcreg && cntreg > srcreg)
181     sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op2r, op1r, op0r, op2r);
182   else if (dstreg == cntreg + 1)
183     sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op0r, op2r, op2r, op1r);
184   else if (dstreg == srcreg + 1)
185     sprintf (outstr, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
186              op0r, op1r, op0r, op2r, op1r, op2r);
187   else if (cntreg + 1 == srcreg)
188     sprintf (outstr, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
189              op2r, op1r, op0r, op2r, op2r, op0r);
190   else if (cntreg == srcreg + 1)
191     sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op0r, op1r, op1r, op0r);
192   else
193     sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d\n\txwr r%d,r%d",
194              op2r, cntreg_1750, op0r, op1r, op2r, cntreg_1750);
195   return outstr;
196 }
197
198 char *
199 mod_regno_adjust (instr, op)
200      char *instr;
201      rtx *op;
202 {
203   static char outstr[40];
204   char *r = (!strncmp (instr, "dvr", 3) ? "r" : "");
205   int modregno_gcc = REGNO (op[3]), modregno_1750 = REGNO (op[0]) + 1;
206
207   if (modregno_gcc == modregno_1750
208       || (reg_renumber != NULL
209           && reg_renumber[modregno_gcc] >= 0
210           && reg_renumber[modregno_gcc] == reg_renumber[modregno_1750]))
211     sprintf (outstr, "%s r%%0,%s%%2", instr, r);
212   else
213     sprintf (outstr, "lr r%d,r%d\n\t%s r%%0,%s%%2\n\txwr r%d,r%d",
214              modregno_gcc, modregno_1750, instr, r, modregno_1750,
215              modregno_gcc);
216   return outstr;
217 }
218
219
220 /* Auxiliary to `nonindirect_operand':
221    Check if op is a valid memory operand for 1750A arith./logic (non-move)
222    instructions. */
223 int
224 memop_valid (op)
225      rtx op;
226 {
227   if (GET_MODE (op) != Pmode && GET_MODE (op) != VOIDmode)
228     return 0;
229   switch (GET_CODE (op))
230     {
231     case MEM:
232     case MINUS:
233     case MULT:
234     case DIV:
235       return 0;
236     case PLUS:
237       if (!memop_valid (XEXP (op, 0)))
238         return 0;
239       return memop_valid (XEXP (op, 1));
240     case REG:
241       if (REGNO (op) > 0)
242         return 1;
243       return 0;
244     case CONST:
245     case CONST_INT:
246     case SYMBOL_REF:
247     case SUBREG:
248       return 1;
249     default:
250       printf ("memop_valid: code=%d\n", (int) GET_CODE (op));
251       return 1;
252     }
253 }
254
255 /* extra predicate for recog: */
256 int
257 nonindirect_operand (op, mode)
258      rtx op;
259      enum machine_mode mode;
260 {
261   int retval;
262
263   switch (GET_CODE (op))
264     {
265     case MEM:
266       retval = memop_valid (XEXP (op, 0));
267       return retval;
268     case REG:
269       return 1;
270     default:
271       if (!CONSTANT_P (op))
272         return 0;
273     }
274   return 1;
275 }
276
277 /* predicate for the MOV instruction: */
278 int
279 mov_memory_operand (op, mode)
280      rtx op;
281      enum machine_mode mode;
282 {
283   return (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG);
284 }
285
286 /* predicate for the STC instruction: */
287 int
288 small_nonneg_const (op, mode)
289      rtx op;
290      enum machine_mode mode;
291 {
292   if (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) <= 15)
293     return 1;
294   return 0;
295 }
296
297 /* predicate for constant zero: */
298 int
299 zero_operand (op, mode)
300      rtx op;
301      enum machine_mode mode;
302 {
303   return op == CONST0_RTX (mode);
304 }
305
306
307 /* predicate for 1750 `B' addressing mode (Base Register with Offset)
308    memory operand */
309 int
310 b_mode_operand (op)
311      rtx op;
312 {
313   if (GET_CODE (op) == MEM)
314     {
315       rtx inner = XEXP (op, 0);
316       if (GET_CODE (inner) == REG && REG_OK_FOR_INDEX_P (inner))
317         return 1;
318       if (GET_CODE (inner) == PLUS)
319         {
320           rtx plus_op0 = XEXP (inner, 0);
321           if (GET_CODE (plus_op0) == REG && REG_OK_FOR_INDEX_P (plus_op0))
322             {
323               rtx plus_op1 = XEXP (inner, 1);
324               if (GET_CODE (plus_op1) == CONST_INT
325                   && INTVAL (plus_op1) >= 0
326                   && INTVAL (plus_op1) <= 255)
327                 return 1;
328             }
329         }
330     }
331   return 0;
332 }
333
334
335 /* Decide whether to output a conditional jump as a "Jump Conditional"
336    or as a "Branch Conditional": */
337
338 int
339 find_jmplbl (labelnum)
340      int labelnum;
341 {
342   int i, found = 0;
343
344   for (i = 0; i <= jmplbl_ndx; i++)
345     if (labelnum == jmplbl[i].num)
346       {
347         found = 1;
348         break;
349       }
350   if (found)
351     return i;
352   return -1;
353 }
354
355 char *
356 branch_or_jump (condition, targetlabel_number)
357      char *condition;
358      int targetlabel_number;
359 {
360   static char buf[30];
361   int index;
362
363   if ((index = find_jmplbl (targetlabel_number)) >= 0)
364     if (program_counter - jmplbl[index].pc < 128)
365       {
366         sprintf (buf, "b%s %%l0", condition);
367         return buf;
368       }
369   sprintf (buf, "jc %s,%%l0", condition);
370   return buf;
371 }
372
373
374 int
375 unsigned_comparison_operator (insn)
376      rtx insn;
377 {
378   switch (GET_CODE (insn))
379     {
380     case GEU:
381     case GTU:
382     case LEU:
383     case LTU:
384       return 1;
385     default:
386       return 0;
387     }
388 }
389
390 int
391 next_cc_user_is_unsigned (insn)
392      rtx insn;
393 {
394   if ( !(insn = next_cc0_user (insn)))
395     abort ();
396   else if (GET_CODE (insn) == JUMP_INSN
397            && GET_CODE (PATTERN (insn)) == SET
398            && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
399     return unsigned_comparison_operator (XEXP (SET_SRC (PATTERN (insn)), 0));
400   else if (GET_CODE (insn) == INSN
401            && GET_CODE (PATTERN (insn)) == SET)
402     return unsigned_comparison_operator (SET_SRC (PATTERN (insn)));
403   else
404     abort ();
405 }
406
407
408 static int addr_inc;
409
410 /* A C compound statement to output to stdio stream STREAM the
411    assembler syntax for an instruction operand X.  X is an RTL
412    expression.
413
414    CODE is a value that can be used to specify one of several ways
415    of printing the operand.  It is used when identical operands
416    must be printed differently depending on the context.  CODE
417    comes from the `%' specification that was used to request
418    printing of the operand.  If the specification was just `%DIGIT'
419    then CODE is 0; if the specification was `%LTR DIGIT' then CODE
420    is the ASCII code for LTR.
421
422    If X is a register, this macro should print the register's name.
423    The names can be found in an array `reg_names' whose type is
424    `char *[]'.  `reg_names' is initialized from `REGISTER_NAMES'.
425
426    When the machine description has a specification `%PUNCT' (a `%'
427    followed by a punctuation character), this macro is called with
428    a null pointer for X and the punctuation character for CODE.
429
430    The 1750 specific codes are:
431    'J' for the negative of a constant
432    'Q' for printing addresses in B mode syntax
433    'd' for the second register in a pair
434    't' for the third register in a triple 
435    'b' for the bit number (using 1750 test bit convention)
436    'B' for the bit number of the 1's complement (for bit clear)
437    'w' for int - 16
438 */
439
440 print_operand (file, x, letter)
441      FILE *file;
442      rtx x;
443      int letter;
444 {
445   switch (GET_CODE (x))
446     {
447     case REG:
448       if (letter == 'd')
449         fprintf (file, "%d", REGNO (x) + 1);
450       else if (letter == 't')
451         fprintf (file, "%d", REGNO (x) + 2);
452       else
453         fprintf (file, "%d", REGNO (x));
454       break;
455
456     case SYMBOL_REF:
457       fprintf (file, "%s", XSTR (x, 0));
458       if (letter == 'A')
459         fprintf (file, "+1");
460       break;
461
462     case LABEL_REF:
463     case CONST:
464     case MEM:
465       if (letter == 'Q')
466         {
467           rtx inner = XEXP (x, 0);
468           switch (GET_CODE (inner))
469             {
470             case REG:
471               fprintf (file, "r%d,0", REGNO (inner));
472               break;
473             case PLUS:
474               fprintf (file, "r%d,%d", REGNO (XEXP (inner, 0)),
475                        INTVAL (XEXP (inner, 1)));
476               break;
477             default:
478               fprintf (file, "[ill Q code=%d]", GET_CODE (inner));
479             }
480         }
481       else
482         {
483           addr_inc = (letter == 'A' ? 1 : 0);
484           output_address (XEXP (x, 0));
485         }
486       break;
487
488     case CONST_DOUBLE:
489 /*    {
490         double value = get_double (x);
491         char fltstr[32];
492         sprintf (fltstr, "%lf", value);
493
494         if (letter == 'D' || letter == 'E')
495           {
496             int i, found = 0;
497             for (i = 0; i <= datalbl_ndx; i++)
498               if (strcmp (fltstr, datalbl[i].value) == 0)
499                 {
500                   found = 1;
501                   break;
502                 }
503             if (!found)
504               {
505                 strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
506                 datalbl[i].name = float_label (letter, value);
507                 datalbl[i].size = (letter == 'E') ? 3 : 2;
508                 check_section (Konst);
509                 fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
510                         (letter == 'E' ? "ef" : "f"), fltstr);
511                 check_section (Normal);
512               }
513           }
514         else if (letter == 'F' || letter == 'G')
515           {
516             int i, found = 0;
517             for (i = 0; i <= datalbl_ndx; i++)
518               if (strcmp (fltstr, datalbl[i].value) == 0)
519                 {
520                   found = 1;
521                   break;
522                 }
523             if (!found)
524               {
525                 fprintf (stderr,
526                    "float value %lfnot found upon label reference\n", value);
527                 strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
528                 datalbl[i].name = float_label (letter, value);
529                 datalbl[i].size = (letter == 'G') ? 3 : 2;
530                 check_section (Konst);
531                 fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
532                         (letter == 'G' ? "ef" : "f"), fltstr);
533                 check_section (Normal);
534               }
535             fprintf (file, "%s ;P_O 'F'", datalbl[i].name);
536           }
537         else
538           fprintf (file, " %s  ;P_O cst_dbl ", fltstr);
539       }
540  */
541       fprintf (file, "%lf", get_double (x));
542       break;
543
544     case CONST_INT:
545       if (letter == 'J')
546         fprintf (file, "%d", -INTVAL (x));
547       if (letter == 'b')
548         fprintf (file, "%d", which_bit (INTVAL (x)));
549       else if (letter == 'B')
550         fprintf (file, "%d", which_bit (~INTVAL (x)));
551       else if (letter == 'w')
552         fprintf (file, "%d", INTVAL (x) - 16);
553       else
554         fprintf (file, "%d", INTVAL (x));
555       break;
556
557     case CODE_LABEL:
558       fprintf (file, "L%d", XINT (x, 3));
559       break;
560
561     case CALL:
562       fprintf (file, "CALL nargs=%d, func is either '%s' or '%s'",
563        XEXP (x, 1), XSTR (XEXP (XEXP (x, 0), 1), 0), XSTR (XEXP (x, 0), 1));
564       break;
565
566     case PLUS:
567       {
568         rtx op0 = XEXP (x, 0), op1 = XEXP (x, 1);
569         int op0code = GET_CODE (op0), op1code = GET_CODE (op1);
570         if (op1code == CONST_INT)
571           switch (op0code)
572             {
573             case REG:
574               fprintf (file, "%d,r%d  ; p_o_PLUS for REG and CONST_INT",
575                        INTVAL (op1), REGNO (op0));
576               break;
577             case SYMBOL_REF:
578               fprintf (file, "%d+%s", INTVAL (op1), XSTR (op0, 0));
579               break;
580             case MEM:
581               fprintf (file, "%d,[mem:", INTVAL (op1));
582               output_address (XEXP (op0, 0));
583               fprintf (file, "] ;P_O plus");
584               break;
585             default:
586               fprintf (file, "p_o_PLUS UFO, code=%d, with CONST=%d",
587                        (int) op0code, INTVAL (op1));
588             }
589         else if (op1code == SYMBOL_REF && op0code == REG)
590           fprintf (file, "%s,r%d  ; P_O: (plus reg sym)",
591                    XSTR (op1, 0), REGNO (op0));
592         else
593           fprintf (file, "p_o_+: op0code=%d, op1code=%d", op0code, op1code);
594       }
595       break;
596
597     default:
598       fprintf (file, "p_o_UFO code=%d", GET_CODE (x));
599     }
600
601   addr_inc = 0;
602 }
603
604 print_operand_address (file, addr)
605      FILE *file;
606      rtx addr;
607 {
608   switch (GET_CODE (addr))
609     {
610     case REG:
611       fprintf (file, "%d,r%d ; P_O_A", addr_inc, REGNO (addr));
612       break;
613     case PLUS:
614       {
615         register rtx x = XEXP (addr, 0), y = XEXP (addr, 1);
616         switch (GET_CODE (x))
617           {
618           case REG:
619             switch (GET_CODE (y))
620               {
621               case CONST:
622                 output_address (XEXP (y, 0));
623                 fprintf (file, ",r%d ;P_O_A reg + const expr", REGNO (x));
624                 break;
625               case CONST_INT:
626                 fprintf (file, "%d,r%d", INTVAL (y) + addr_inc, REGNO (x));
627                 break;
628               case SYMBOL_REF:
629                 fprintf (file, "%s", XSTR (y, 0));
630                 if (addr_inc)
631                   fprintf (file, "+%d", addr_inc);
632                 fprintf (file, ",r%d  ; P_O_A reg + sym", REGNO (x));
633                 break;
634               case LABEL_REF:
635                 output_address (XEXP (y, 0));
636                 fprintf (file, ",r%d  ; P_O_A reg + label", REGNO (x));
637                 break;
638               default:
639                 fprintf (file, "[P_O_A reg%d+UFO code=%d]",
640                          REGNO (x), GET_CODE (y));
641               }
642             break;
643           case LABEL_REF:
644             output_address (XEXP (x, 0));
645             break;
646           case SYMBOL_REF:
647             switch (GET_CODE (y))
648               {
649               case CONST_INT:
650                 fprintf (file, "%d+%s", INTVAL (y) + addr_inc, XSTR (x, 0));
651                 break;
652               case REG:
653                 fprintf (file, "%s,r%d ;P_O_A sym + reg",
654                          XSTR (x, 0), REGNO (y));
655                 break;
656               default:
657                 fprintf (file, "P_O_A sym/lab+UFO[sym=%s,code(y)=%d]",
658                          XSTR (x, 0), GET_CODE (y));
659               }
660             break;
661           case CONST:
662             output_address (XEXP (x, 0));
663             if (GET_CODE (y) == REG)
664               fprintf (file, ",r%d ;P_O_A const + reg", REGNO (x));
665             else
666               fprintf (file, "P_O_A const+UFO code(y)=%d]", GET_CODE (y));
667             break;
668           case MEM:
669             output_address (y);
670             fprintf (file, ",[mem:");
671             output_address (XEXP (x, 0));
672             fprintf (file, "] ;P_O_A plus");
673             break;
674           default:
675             fprintf (file, "P_O_A plus op1_UFO[code1=%d,code2=%d]",
676                      GET_CODE (x), GET_CODE (y));
677           }
678       }
679       break;
680     case CONST_INT:
681       if (INTVAL (addr) < 0x10000 && INTVAL (addr) >= -0x10000)
682         fprintf (file, "%d ; p_o_a const addr?!", INTVAL (addr));
683       else
684         {
685           fprintf (file, "[p_o_a=ILLEGAL_CONST]");
686           output_addr_const (file, addr);
687         }
688       break;
689     case LABEL_REF:
690     case SYMBOL_REF:
691       fprintf (file, "%s", XSTR (addr, 0));
692       if (addr_inc)
693         fprintf (file, "+%d", addr_inc);
694       break;
695     case MEM:
696       fprintf (file, "[memUFO:");
697       output_address (XEXP (addr, 0));
698       fprintf (file, "]");
699       break;
700     case CONST:
701       output_address (XEXP (addr, 0));
702       fprintf (file, " ;P_O_A const");
703       break;
704     case CODE_LABEL:
705       fprintf (file, "L%d", XINT (addr, 3));
706       break;
707     default:
708       fprintf (file, " p_o_a UFO, code=%d val=0x%x",
709                (int) GET_CODE (addr), INTVAL (addr));
710       break;
711     }
712   addr_inc = 0;
713 }
714
715
716 /*
717  *  Return non zero if the LS 16 bits of the given value has just one bit set,
718  *  otherwise return zero. Note this function may be used to detect one
719  *  bit clear by inverting the param.
720  */
721 int
722 one_bit_set_p (x)
723      int x;
724 {
725   x &= 0xffff; 
726   return x && (x & (x - 1)) == 0;
727 }
728
729
730 /*
731  * Return the number of the least significant bit set, using the  same
732  * convention for bit numbering as in the MIL-STD-1750 sb instruction.
733  */
734 int
735 which_bit (x)
736      int x;
737 {
738   int b = 15;
739
740   while (b > 0 && (x & 1) == 0)
741     {
742       b--;
743       x >>= 1;
744     }
745
746   return b;
747 }
748
749